Added title in about us and updated apis
|
@ -0,0 +1,29 @@
|
||||||
|
"""add title in aboutUs
|
||||||
|
|
||||||
|
Revision ID: 94afd163eba3
|
||||||
|
Revises: 8e38378fd2f3
|
||||||
|
Create Date: 2024-10-05 10:26:21.093141
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
import sqlmodel.sql.sqltypes
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '94afd163eba3'
|
||||||
|
down_revision = '8e38378fd2f3'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('aboutus', sa.Column('title', sqlmodel.sql.sqltypes.AutoString(length=255), nullable=False))
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column('aboutus', 'title')
|
||||||
|
# ### end Alembic commands ###
|
|
@ -24,6 +24,7 @@ async def create_aboutUs(
|
||||||
session: SessionDep,
|
session: SessionDep,
|
||||||
current_user: CurrentUser,
|
current_user: CurrentUser,
|
||||||
description: str = Form(),
|
description: str = Form(),
|
||||||
|
title: str = Form(),
|
||||||
image: Annotated[UploadFile, File()],
|
image: Annotated[UploadFile, File()],
|
||||||
index: int = Form()
|
index: int = Form()
|
||||||
) -> Any:
|
) -> Any:
|
||||||
|
@ -33,7 +34,7 @@ async def create_aboutUs(
|
||||||
validate_file_size_type(image)
|
validate_file_size_type(image)
|
||||||
imageUrl = await save_picture(file=image, folderName="tmp")
|
imageUrl = await save_picture(file=image, folderName="tmp")
|
||||||
# aboutus_in.image = imageUrl
|
# aboutus_in.image = imageUrl
|
||||||
aboutUs_in = AboutUsCreate(description=description, image=imageUrl, index=index)
|
aboutUs_in = AboutUsCreate(description=description, image=imageUrl, index=index ,title=title)
|
||||||
aboutUs = AboutUs.from_orm(aboutUs_in)
|
aboutUs = AboutUs.from_orm(aboutUs_in)
|
||||||
session.add(aboutUs)
|
session.add(aboutUs)
|
||||||
session.commit()
|
session.commit()
|
||||||
|
@ -49,6 +50,7 @@ async def edit_aboutUs(
|
||||||
id: uuid.UUID,
|
id: uuid.UUID,
|
||||||
description: str = Form(),
|
description: str = Form(),
|
||||||
image: Annotated[UploadFile, File()] = None,
|
image: Annotated[UploadFile, File()] = None,
|
||||||
|
title: str = Form(),
|
||||||
index: int = Form()
|
index: int = Form()
|
||||||
) -> Any:
|
) -> Any:
|
||||||
aboutUs = session.get(AboutUs, id)
|
aboutUs = session.get(AboutUs, id)
|
||||||
|
@ -57,9 +59,9 @@ async def edit_aboutUs(
|
||||||
validate_file_size_type(image)
|
validate_file_size_type(image)
|
||||||
imageUrl = await save_picture(file=image, folderName="tmp")
|
imageUrl = await save_picture(file=image, folderName="tmp")
|
||||||
await del_picture(aboutUs.image)
|
await del_picture(aboutUs.image)
|
||||||
aboutUs_in = AboutsUpdate(description=description, image=imageUrl, index=index)
|
aboutUs_in = AboutsUpdate(description=description, image=imageUrl, index=index, title=title)
|
||||||
else :
|
else :
|
||||||
aboutUs_in = AboutsUpdate(description=description, image=aboutUs.image, index=index)
|
aboutUs_in = AboutsUpdate(description=description, image=aboutUs.image, index=index, title=title)
|
||||||
|
|
||||||
update_dict = aboutUs_in.model_dump(exclude_unset=True)
|
update_dict = aboutUs_in.model_dump(exclude_unset=True)
|
||||||
aboutUs.sqlmodel_update(update_dict)
|
aboutUs.sqlmodel_update(update_dict)
|
||||||
|
|
|
@ -26,7 +26,7 @@ if settings.BACKEND_CORS_ORIGINS:
|
||||||
CORSMiddleware,
|
CORSMiddleware,
|
||||||
allow_origins=[
|
allow_origins=[
|
||||||
str(origin).strip("/") for origin in settings.BACKEND_CORS_ORIGINS
|
str(origin).strip("/") for origin in settings.BACKEND_CORS_ORIGINS
|
||||||
] + ["http://localhost:3000"],
|
] + ["http://localhost:3000"]+["http://localhost:5173"]+["http://localhost:5173/aboutUs"],
|
||||||
allow_credentials=True,
|
allow_credentials=True,
|
||||||
allow_methods=["*"],
|
allow_methods=["*"],
|
||||||
allow_headers=["*"],
|
allow_headers=["*"],
|
||||||
|
|
|
@ -166,6 +166,7 @@ class Setting(SettingBase, table=True):
|
||||||
class AboutUsBase(SQLModel):
|
class AboutUsBase(SQLModel):
|
||||||
description: str = Field(max_length=1024)
|
description: str = Field(max_length=1024)
|
||||||
image:str | None = Field(default=None, max_length=255)
|
image:str | None = Field(default=None, max_length=255)
|
||||||
|
title: str = Field(max_length=255)
|
||||||
index: int
|
index: int
|
||||||
|
|
||||||
class AboutUsCreate(AboutUsBase):
|
class AboutUsCreate(AboutUsBase):
|
||||||
|
@ -209,6 +210,8 @@ class CoursePublic(CourseBase):
|
||||||
id: uuid.UUID
|
id: uuid.UUID
|
||||||
title: str
|
title: str
|
||||||
images: list["Image"]
|
images: list["Image"]
|
||||||
|
info_images: list["Info_Image"]
|
||||||
|
schedule: list["Schedule"]
|
||||||
created_at: datetime
|
created_at: datetime
|
||||||
|
|
||||||
class CoursesPublic(SQLModel):
|
class CoursesPublic(SQLModel):
|
||||||
|
|
After Width: | Height: | Size: 632 KiB |
Before Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 632 KiB |
After Width: | Height: | Size: 632 KiB |
Before Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 2.0 MiB |
After Width: | Height: | Size: 632 KiB |
After Width: | Height: | Size: 632 KiB |
After Width: | Height: | Size: 632 KiB |
After Width: | Height: | Size: 632 KiB |
After Width: | Height: | Size: 1.2 MiB |
After Width: | Height: | Size: 632 KiB |
After Width: | Height: | Size: 632 KiB |
After Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 632 KiB |
After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 79 KiB |
After Width: | Height: | Size: 632 KiB |
|
@ -150,6 +150,7 @@ export type AboutUssPublic = {
|
||||||
export type AboutUsPublic = {
|
export type AboutUsPublic = {
|
||||||
index: number,
|
index: number,
|
||||||
description: string,
|
description: string,
|
||||||
|
title: string,
|
||||||
image: string,
|
image: string,
|
||||||
id: string
|
id: string
|
||||||
}
|
}
|
||||||
|
@ -157,12 +158,14 @@ export type AboutUsPublic = {
|
||||||
export type AboutUsCreate = {
|
export type AboutUsCreate = {
|
||||||
index: number,
|
index: number,
|
||||||
description: string,
|
description: string,
|
||||||
|
title: string,
|
||||||
image: File,
|
image: File,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AboutUsUpdate = {
|
export type AboutUsUpdate = {
|
||||||
index: number,
|
index: number,
|
||||||
description: string,
|
description: string,
|
||||||
|
title: string,
|
||||||
image?: File | undefined | null,
|
image?: File | undefined | null,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -134,7 +134,7 @@ const AddAboutUs = ({ isOpen, onClose }: AddAboutUsProps) => {
|
||||||
}
|
}
|
||||||
mutation.mutate(data)
|
mutation.mutate(data)
|
||||||
console.log(data)
|
console.log(data)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -152,6 +152,20 @@ const AddAboutUs = ({ isOpen, onClose }: AddAboutUsProps) => {
|
||||||
<ModalCloseButton />
|
<ModalCloseButton />
|
||||||
|
|
||||||
<ModalBody pb={30}>
|
<ModalBody pb={30}>
|
||||||
|
<FormControl isRequired isInvalid={!!errors.title}>
|
||||||
|
<FormLabel htmlFor="title">Title</FormLabel>
|
||||||
|
<Input
|
||||||
|
id="title"
|
||||||
|
{...register("title", {
|
||||||
|
required: "Title is required.",
|
||||||
|
})}
|
||||||
|
placeholder="Title"
|
||||||
|
type="text"
|
||||||
|
/>
|
||||||
|
{errors.title && (
|
||||||
|
<FormErrorMessage>{errors.title.message}</FormErrorMessage>
|
||||||
|
)}
|
||||||
|
</FormControl>
|
||||||
<FormControl isRequired isInvalid={!!errors.description}>
|
<FormControl isRequired isInvalid={!!errors.description}>
|
||||||
<Editor
|
<Editor
|
||||||
editorState={editorState}
|
editorState={editorState}
|
||||||
|
@ -186,7 +200,7 @@ const AddAboutUs = ({ isOpen, onClose }: AddAboutUsProps) => {
|
||||||
<NumberDecrementStepper />
|
<NumberDecrementStepper />
|
||||||
</NumberInputStepper>
|
</NumberInputStepper>
|
||||||
</NumberInput>
|
</NumberInput>
|
||||||
|
|
||||||
{errors.index && (
|
{errors.index && (
|
||||||
<FormErrorMessage>{errors.index.message}</FormErrorMessage>
|
<FormErrorMessage>{errors.index.message}</FormErrorMessage>
|
||||||
)}
|
)}
|
||||||
|
@ -195,7 +209,7 @@ const AddAboutUs = ({ isOpen, onClose }: AddAboutUsProps) => {
|
||||||
<FormControl isInvalid={!!errors.image} isRequired>
|
<FormControl isInvalid={!!errors.image} isRequired>
|
||||||
<FormLabel>{'Image Upload'}</FormLabel>
|
<FormLabel>{'Image Upload'}</FormLabel>
|
||||||
|
|
||||||
|
|
||||||
<input type="file" {...register("image", {
|
<input type="file" {...register("image", {
|
||||||
required: "index is required.",
|
required: "index is required.",
|
||||||
})} />
|
})} />
|
||||||
|
|
|
@ -89,6 +89,7 @@ const EditAboutUs = ({ aboutUs, isOpen, onClose }: EditAboutUsProps) => {
|
||||||
criteriaMode: "all",
|
criteriaMode: "all",
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
index: aboutUs.index,
|
index: aboutUs.index,
|
||||||
|
title: aboutUs.title,
|
||||||
description: aboutUs.description,
|
description: aboutUs.description,
|
||||||
image: undefined,
|
image: undefined,
|
||||||
},
|
},
|
||||||
|
@ -167,6 +168,20 @@ const EditAboutUs = ({ aboutUs, isOpen, onClose }: EditAboutUsProps) => {
|
||||||
<Box boxSize='auto'>
|
<Box boxSize='auto'>
|
||||||
<Image src={url + "/" + aboutUs.image} />
|
<Image src={url + "/" + aboutUs.image} />
|
||||||
</Box>
|
</Box>
|
||||||
|
<FormControl isRequired isInvalid={!!errors.title}>
|
||||||
|
<FormLabel htmlFor="title">Title</FormLabel>
|
||||||
|
<Input
|
||||||
|
id="title"
|
||||||
|
{...register("title", {
|
||||||
|
required: "Title is required.",
|
||||||
|
})}
|
||||||
|
placeholder="Title"
|
||||||
|
type="text"
|
||||||
|
/>
|
||||||
|
{errors.title && (
|
||||||
|
<FormErrorMessage>{errors.title.message}</FormErrorMessage>
|
||||||
|
)}
|
||||||
|
</FormControl>
|
||||||
<FormControl isRequired isInvalid={!!errors.description}>
|
<FormControl isRequired isInvalid={!!errors.description}>
|
||||||
<Editor
|
<Editor
|
||||||
editorState={editorState}
|
editorState={editorState}
|
||||||
|
|
|
@ -36,7 +36,7 @@ import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
|
||||||
const CourseDetails = () => {
|
const CourseDetails = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const courseDetails = queryClient.getQueryData(['course']) as CourseDetailsPublic | undefined;
|
const courseDetails = queryClient.getQueryData(['course']) as CourseDetailsPublic | undefined;
|
||||||
|
|
||||||
const toolbar = {
|
const toolbar = {
|
||||||
options: ['inline', 'blockType', 'fontSize', 'list', 'textAlign', 'history', 'embedded', 'emoji', 'image'],
|
options: ['inline', 'blockType', 'fontSize', 'list', 'textAlign', 'history', 'embedded', 'emoji', 'image'],
|
||||||
inline: { inDropdown: true },
|
inline: { inDropdown: true },
|
||||||
|
@ -78,9 +78,14 @@ const CourseDetails = () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
reset({}, { keepDirty: true });
|
||||||
if (courseDetails) {
|
if (courseDetails) {
|
||||||
setValue('title', courseDetails.title);
|
setValue('title', courseDetails.title, { shouldDirty: true });
|
||||||
setValue('sort_description', courseDetails.sort_description);
|
setValue('sort_description', courseDetails.sort_description, { shouldDirty: true });
|
||||||
|
setValue('long_description', courseDetails.long_description, { shouldDirty: true });
|
||||||
|
setValue('remark', courseDetails.remark, { shouldDirty: true });
|
||||||
|
setValue('information', courseDetails.information, { shouldDirty: true });
|
||||||
|
setValue('contant', courseDetails.contant, { shouldDirty: true });
|
||||||
// Update other form fields as needed
|
// Update other form fields as needed
|
||||||
}
|
}
|
||||||
if (courseDetails?.long_description) {
|
if (courseDetails?.long_description) {
|
||||||
|
@ -89,7 +94,7 @@ const CourseDetails = () => {
|
||||||
const contentState = ContentState.createFromBlockArray(contentBlock.contentBlocks);
|
const contentState = ContentState.createFromBlockArray(contentBlock.contentBlocks);
|
||||||
const editorState = EditorState.createWithContent(contentState);
|
const editorState = EditorState.createWithContent(contentState);
|
||||||
setLongDescriptionEditorState(editorState);
|
setLongDescriptionEditorState(editorState);
|
||||||
setValue('long_description', longDescription);
|
// setValue('long_description', courseDetails.long_description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (courseDetails?.remark) {
|
if (courseDetails?.remark) {
|
||||||
|
@ -98,7 +103,7 @@ const CourseDetails = () => {
|
||||||
const contentState = ContentState.createFromBlockArray(contentBlock.contentBlocks);
|
const contentState = ContentState.createFromBlockArray(contentBlock.contentBlocks);
|
||||||
const editorState = EditorState.createWithContent(contentState);
|
const editorState = EditorState.createWithContent(contentState);
|
||||||
setRemarksEditorState(editorState);
|
setRemarksEditorState(editorState);
|
||||||
setValue('remark', remarks);
|
//setValue('remark', courseDetails.remark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (courseDetails?.information) {
|
if (courseDetails?.information) {
|
||||||
|
@ -107,7 +112,7 @@ const CourseDetails = () => {
|
||||||
const contentState = ContentState.createFromBlockArray(contentBlock.contentBlocks);
|
const contentState = ContentState.createFromBlockArray(contentBlock.contentBlocks);
|
||||||
const editorState = EditorState.createWithContent(contentState);
|
const editorState = EditorState.createWithContent(contentState);
|
||||||
setInfoEditorState(editorState);
|
setInfoEditorState(editorState);
|
||||||
setValue('information', info);
|
//setValue('information', courseDetails.information);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (courseDetails?.contant) {
|
if (courseDetails?.contant) {
|
||||||
|
@ -116,11 +121,10 @@ const CourseDetails = () => {
|
||||||
const contentState = ContentState.createFromBlockArray(contentBlock.contentBlocks);
|
const contentState = ContentState.createFromBlockArray(contentBlock.contentBlocks);
|
||||||
const editorState = EditorState.createWithContent(contentState);
|
const editorState = EditorState.createWithContent(contentState);
|
||||||
setContentEditorState(editorState);
|
setContentEditorState(editorState);
|
||||||
setValue('contant', contents);
|
//setValue('contant', courseDetails.contant);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [courseDetails]);
|
}, [courseDetails]);
|
||||||
|
|
||||||
const mutation = useMutation({
|
const mutation = useMutation({
|
||||||
mutationFn: (data: CourseCreate) =>
|
mutationFn: (data: CourseCreate) =>
|
||||||
CoursesService.updateCourse({ id: courseDetails?.id ?? '', requestBody: data }),
|
CoursesService.updateCourse({ id: courseDetails?.id ?? '', requestBody: data }),
|
||||||
|
|
|
@ -51,7 +51,7 @@ function EditCourse() {
|
||||||
return (
|
return (
|
||||||
<Container maxW="full">
|
<Container maxW="full">
|
||||||
<Heading size="lg" textAlign={{ base: "center", md: "left" }} py={12}>
|
<Heading size="lg" textAlign={{ base: "center", md: "left" }} py={12}>
|
||||||
User Settings
|
Courses
|
||||||
</Heading>
|
</Heading>
|
||||||
<Tabs variant="enclosed">
|
<Tabs variant="enclosed">
|
||||||
<TabList>
|
<TabList>
|
||||||
|
|
|
@ -76,6 +76,7 @@ function AboutUsTable() {
|
||||||
<Thead>
|
<Thead>
|
||||||
<Tr>
|
<Tr>
|
||||||
<Th>ID</Th>
|
<Th>ID</Th>
|
||||||
|
<Th>Title</Th>
|
||||||
<Th>Description</Th>
|
<Th>Description</Th>
|
||||||
<Th>Image</Th>
|
<Th>Image</Th>
|
||||||
<Th>Index</Th>
|
<Th>Index</Th>
|
||||||
|
@ -97,6 +98,12 @@ function AboutUsTable() {
|
||||||
{aboutUs?.data.map((aboutUs) => (
|
{aboutUs?.data.map((aboutUs) => (
|
||||||
<Tr key={aboutUs.id} opacity={isPlaceholderData ? 0.5 : 1}>
|
<Tr key={aboutUs.id} opacity={isPlaceholderData ? 0.5 : 1}>
|
||||||
<Td isTruncated maxWidth="50">{aboutUs.id}</Td>
|
<Td isTruncated maxWidth="50">{aboutUs.id}</Td>
|
||||||
|
<Td
|
||||||
|
whiteSpace="pre-line"
|
||||||
|
maxWidth="350px"
|
||||||
|
>
|
||||||
|
{parse(aboutUs.title)}
|
||||||
|
</Td>
|
||||||
|
|
||||||
<Td
|
<Td
|
||||||
whiteSpace="pre-line"
|
whiteSpace="pre-line"
|
||||||
|
|