начал работу на функционалом Thread, мелкие правки

This commit is contained in:
dyakonovr 2024-03-26 13:35:03 +04:00
parent 7ccdcd4227
commit ed3f2cb63e
18 changed files with 329 additions and 3 deletions

9
client/.prettierrc Normal file
View File

@ -0,0 +1,9 @@
{
"semi": true,
"jsxSingleQuote": false,
"bracketSpacing": true,
"trailingComma": "none",
"printWidth": 90,
"tabWidth": 2,
"arrowParens": "always"
}

View File

@ -1 +0,0 @@
module.exports = {}

View File

@ -9,6 +9,8 @@ import UserEdit from "./components/User/Edit";
import SectionsList from "./components/Section/List";
import SectionCreate from "./components/Section/Create";
import SectionEdit from "./components/Section/Edit";
import ThreadsList from "./components/Thread/List";
import ThreadCreate from "./components/Thread/Create";
function App() {
return (
@ -31,6 +33,12 @@ function App() {
create={<SectionCreate />}
edit={<SectionEdit />}
/>
<Resource
name="threads"
list={<ThreadsList />}
create={<ThreadCreate />}
// edit={<SectionEdit />}
/>
</Admin>
);
}

View File

@ -0,0 +1,26 @@
import {
Create,
ReferenceInput,
SelectInput,
SimpleForm,
TextInput,
required
} from "react-admin";
function ThreadCreate() {
return (
<Create>
<SimpleForm>
<TextInput source="name" fullWidth />
<ReferenceInput source="section_id" reference="sections">
<SelectInput optionText="name" fullWidth validate={required()} />
</ReferenceInput>
<ReferenceInput source="creator_id" reference="users">
<SelectInput optionText="nickname" fullWidth validate={required()} />
</ReferenceInput>
</SimpleForm>
</Create>
);
}
export default ThreadCreate;

View File

@ -0,0 +1,31 @@
import {
Edit,
ReferenceInput,
SelectInput,
SimpleForm,
TextInput,
useGetRecordId,
} from "react-admin";
import Title from "../Title";
function SectionEdit() {
const recordId = useGetRecordId();
return (
<Edit title={<Title prefixText="Роль" />} actions={false}>
<SimpleForm>
<TextInput source="name" fullWidth />
<ReferenceInput
source="root_section_id"
reference="sections"
filter={{ id: recordId }}
>
<SelectInput optionText="name" fullWidth />
</ReferenceInput>
</SimpleForm>
</Edit>
);
}
export default SectionEdit;

View File

@ -0,0 +1,17 @@
import { List, Datagrid, TextField, EditButton } from "react-admin";
function ThreadsList() {
return (
<List>
<Datagrid>
<TextField source="id" />
<TextField source="name" />
<TextField source="section_id" />
<TextField source="creator_id" />
<EditButton />
</Datagrid>
</List>
);
};
export default ThreadsList;

View File

@ -0,0 +1,145 @@
import { type Order } from "sequelize";
import Section from "../../models/section.model";
import { ApiErrorHandler } from "../../error/api-error.handler";
import Thread from "../../models/thread.model";
import type { IThreadDto } from "./thread.dto";
import type { NextFunction, Request, Response } from "express";
import type {
FilterQueryParamType,
RangeQueryParamType,
SortQueryParamType
} from "../query-param.types";
class ThreadController {
getAll = async (req: Request, res: Response, next: NextFunction) => {
try {
const range: RangeQueryParamType = req.query.range
? JSON.parse(req.query.range.toString())
: [0, 10];
const sort: SortQueryParamType = req.query.sort
? JSON.parse(req.query.sort.toString())
: ["id", "ASC"];
const threads = await Thread.findAndCountAll({
offset: range[0],
limit: range[1] - range[0] + 1,
order: [sort] as Order
});
return res.json({ data: threads.rows, total: threads.count });
} catch (error) {
next(ApiErrorHandler.internal((error as Error).message));
}
};
getMany = async (
req: Request,
res: Response<{ data: Thread[] }>,
next: NextFunction
) => {
try {
const filter: FilterQueryParamType = req.query.filter
? JSON.parse(req.query.filter.toString())
: { ids: [] };
const threads = await Thread.findAll({
where: { id: filter.ids as number[] }
});
return res.json({ data: threads });
} catch (error) {
next(ApiErrorHandler.internal((error as Error).message));
}
};
create = async (
req: Request<object, object, IThreadDto>,
res: Response<Thread>,
next: NextFunction
) => {
try {
const { name, section_id, creator_id } = req.body;
const thread = await Thread.create({ name, section_id, creator_id });
return res.json(thread);
} catch (error) {
next(ApiErrorHandler.internal((error as Error).message));
}
};
getById = async (
req: Request<{ id: number }>,
res: Response<Thread>,
next: NextFunction
) => {
try {
const { id } = req.params;
const thread = await Thread.findByPk(id);
if (!thread) return next(ApiErrorHandler.notFound("Такой роли не найдено"));
return res.json(thread);
} catch (error) {
next(ApiErrorHandler.internal((error as Error).message));
}
};
update = async (
req: Request<{ id: number }, object, IThreadDto>,
res: Response<Thread>,
next: NextFunction
) => {
try {
const { id } = req.params;
const { name, section_id, creator_id } = req.body;
const thread = await Thread.findByPk(id);
if (!thread) return next(ApiErrorHandler.internal("Такой роли не найдено"));
thread.name = name;
thread.section_id = section_id;
thread.creator_id = creator_id;
await thread.save();
return res.json(thread);
} catch (error) {
next(ApiErrorHandler.internal((error as Error).message));
}
};
delete = async (
req: Request<{ id: number }>,
res: Response<Section>,
next: NextFunction
) => {
try {
const { id } = req.params;
const section = await Section.findByPk(id);
if (!section) return next(ApiErrorHandler.internal("Такой роли не найдено"));
await section.destroy();
return res.json(section);
} catch (error) {
next(ApiErrorHandler.internal((error as Error).message));
}
};
deleteMany = async (
req: Request,
res: Response<{ data: Section[] }>,
next: NextFunction
) => {
try {
const filter: FilterQueryParamType = req.query.filter
? JSON.parse(req.query.filter.toString())
: {};
const sections = await Section.findAll({ where: filter });
Section.destroy({ where: filter });
return res.json({ data: sections });
} catch (error) {
next(ApiErrorHandler.internal((error as Error).message));
}
};
}
export default new ThreadController();

View File

@ -0,0 +1,5 @@
export interface IThreadDto {
name: string;
section_id: number;
creator_id: number;
}

View File

@ -3,6 +3,7 @@ import { Sequelize } from "sequelize-typescript";
import Role from "./models/role.model";
import User from "./models/user.model";
import Section from "./models/section.model";
import Thread from "./models/thread.model";
dotenv.config();
@ -13,5 +14,5 @@ export const sequelize = new Sequelize({
password: process.env.DB_PASSWORD,
host: process.env.DB_HOST,
port: process.env.DB_PORT,
models: [Role, User, Section]
models: [Role, User, Section, Thread]
});

View File

@ -10,6 +10,7 @@ import {
BelongsTo,
HasMany
} from "sequelize-typescript";
import Thread from "./thread.model";
@Table({
tableName: "sections",
@ -48,4 +49,7 @@ export default class Section extends Model {
@HasMany(() => Section, "root_section_id")
declare inner_sections: Section[];
// @HasMany(() => Thread, "section_id")
// declare threads: Thread[];
}

View File

@ -0,0 +1,60 @@
import {
Table,
Column,
Model,
DataType,
Length,
UpdatedAt,
CreatedAt,
ForeignKey,
BelongsTo
} from "sequelize-typescript";
import Section from "./section.model";
import User from "./user.model";
@Table({
tableName: "threads",
modelName: "Thread"
})
export default class Thread extends Model {
@Column({
primaryKey: true,
autoIncrement: true,
type: DataType.INTEGER
})
declare id: number;
@Length({ min: 1 })
@Column({
allowNull: false,
defaultValue: "Unknown",
type: DataType.STRING
})
declare name: string;
@CreatedAt
declare created_at: Date;
@UpdatedAt
declare updated_at: Date;
@ForeignKey(() => Section)
@Column({
type: DataType.INTEGER,
allowNull: false
})
declare section_id: number;
@BelongsTo(() => Section, "section_id")
declare section: Section;
@ForeignKey(() => User)
@Column({
type: DataType.INTEGER,
allowNull: false
})
declare creator_id: number | null;
@BelongsTo(() => User, "creator_id")
declare creator: User;
}

View File

@ -7,9 +7,11 @@ import {
CreatedAt,
UpdatedAt,
ForeignKey,
BelongsTo
BelongsTo,
HasMany
} from "sequelize-typescript";
import Role from "./role.model";
import Thread from "./thread.model";
@Table({
timestamps: true,
@ -69,4 +71,7 @@ export default class User extends Model {
@BelongsTo(() => Role, "role_id")
declare role: Role;
// @HasMany(() => Thread, "thread_id")
// declare threads: Thread[];
}

View File

@ -2,9 +2,11 @@ import { Router } from "express";
import roleRouter from "./routes/role.router";
import userRouter from "./routes/user.router";
import sectionRouter from "./routes/section.router";
import threadRouter from "./routes/thread.router";
export const router = Router();
router.use("/roles", roleRouter);
router.use("/users", userRouter);
router.use("/sections", sectionRouter);
router.use("/threads", threadRouter);

View File

@ -0,0 +1,14 @@
import { Router } from "express";
import ThreadController from "../../controllers/thread/thread.controller";
const threadRouter = Router();
threadRouter.post("/", ThreadController.create);
threadRouter.get("/", ThreadController.getAll);
threadRouter.get("/get-many", ThreadController.getMany);
threadRouter.get("/:id", ThreadController.getById);
threadRouter.put("/:id", ThreadController.update);
threadRouter.delete("/delete-many", ThreadController.deleteMany);
threadRouter.delete("/:id", ThreadController.delete);
export default threadRouter;