fix image
This commit is contained in:
parent
e8e50d0526
commit
d6c8ff6468
|
|
@ -1,43 +1,33 @@
|
||||||
import {
|
import {
|
||||||
DownloadOutlined,
|
|
||||||
RotateLeftOutlined,
|
RotateLeftOutlined,
|
||||||
RotateRightOutlined,
|
RotateRightOutlined,
|
||||||
SwapOutlined,
|
SwapOutlined,
|
||||||
ZoomInOutlined,
|
ZoomInOutlined,
|
||||||
ZoomOutOutlined,
|
ZoomOutOutlined,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import React from "react";
|
import React, { useState } from "react";
|
||||||
import { Image, Space } from "antd";
|
import { Image, Space } from "antd";
|
||||||
import useImageError from "../../Hooks/useImageError";
|
import { CiImageOff } from "react-icons/ci"; // Assuming you're using this icon from react-icons
|
||||||
import { ErrorImage } from "../../Layout/app/Const";
|
|
||||||
|
|
||||||
const ColumnsImage = ({ src }: any) => {
|
const ColumnsImage = ({ src }: any) => {
|
||||||
const imageUrl = src || ErrorImage;
|
const [hasError, setHasError] = useState(false); // Track if the image has an error
|
||||||
|
|
||||||
const handleError = useImageError;
|
const imageUrl = src;
|
||||||
// or you can download flipped and rotated image
|
|
||||||
// https://codesandbox.io/s/zi-ding-yi-gong-ju-lan-antd-5-7-0-forked-c9jvmp
|
|
||||||
const onDownload = () => {
|
|
||||||
fetch(src)
|
|
||||||
.then((response) => response.blob())
|
|
||||||
.then((blob) => {
|
|
||||||
const url = URL.createObjectURL(new Blob([blob]));
|
|
||||||
const link = document.createElement("a");
|
|
||||||
link.href = url;
|
|
||||||
link.download = "image.png";
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
URL.revokeObjectURL(url);
|
|
||||||
link.remove();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
if (hasError) {
|
||||||
|
// If there is an error, display the fallback icon
|
||||||
|
return <CiImageOff />;
|
||||||
|
}
|
||||||
|
if(!imageUrl){
|
||||||
|
return <CiImageOff />;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<Image
|
<Image
|
||||||
width={45}
|
width={45}
|
||||||
height={45}
|
height={45}
|
||||||
src={imageUrl}
|
src={imageUrl}
|
||||||
className="p-1 mb-1 columnImage "
|
className="p-1 mb-1 columnImage"
|
||||||
|
onError={() => setHasError(true)} // Triggered when image fails to load
|
||||||
preview={{
|
preview={{
|
||||||
toolbarRender: (
|
toolbarRender: (
|
||||||
_,
|
_,
|
||||||
|
|
@ -54,7 +44,6 @@ const ColumnsImage = ({ src }: any) => {
|
||||||
},
|
},
|
||||||
) => (
|
) => (
|
||||||
<Space size={12} className="toolbar-wrapper">
|
<Space size={12} className="toolbar-wrapper">
|
||||||
{/* <DownloadOutlined onClick={onDownload} /> */}
|
|
||||||
<SwapOutlined rotate={90} onClick={onFlipY} />
|
<SwapOutlined rotate={90} onClick={onFlipY} />
|
||||||
<SwapOutlined onClick={onFlipX} />
|
<SwapOutlined onClick={onFlipX} />
|
||||||
<RotateLeftOutlined onClick={onRotateLeft} />
|
<RotateLeftOutlined onClick={onRotateLeft} />
|
||||||
|
|
@ -64,19 +53,8 @@ const ColumnsImage = ({ src }: any) => {
|
||||||
</Space>
|
</Space>
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
onError={handleError}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ColumnsImage;
|
export default ColumnsImage;
|
||||||
|
|
||||||
// {
|
|
||||||
// name: t("image"),
|
|
||||||
// center: "true",
|
|
||||||
// cell: (row: any) => {
|
|
||||||
// return (
|
|
||||||
// <ColumnsImage src={row?.image} />
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,14 @@ const FilterLayout = ({
|
||||||
filterTitle,
|
filterTitle,
|
||||||
sub_children,
|
sub_children,
|
||||||
search_by = "name",
|
search_by = "name",
|
||||||
width = "500px"
|
width = "500px",
|
||||||
|
haveFilter=true
|
||||||
}: {
|
}: {
|
||||||
filterTitle: string;
|
filterTitle: string;
|
||||||
sub_children: any;
|
sub_children: any;
|
||||||
search_by?:string
|
search_by?:string
|
||||||
width?:string
|
width?:string
|
||||||
|
haveFilter?:boolean
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const translateArray = translateOptions(search_array, t);
|
const translateArray = translateOptions(search_array, t);
|
||||||
|
|
@ -46,6 +48,8 @@ const FilterLayout = ({
|
||||||
<div className="model_sub_children">{sub_children}</div>
|
<div className="model_sub_children">{sub_children}</div>
|
||||||
<FilterSubmit />
|
<FilterSubmit />
|
||||||
</FilterBody>
|
</FilterBody>
|
||||||
|
{haveFilter &&
|
||||||
|
|
||||||
<div className="filter_button" onClick={() => setIsOpen(true)}>
|
<div className="filter_button" onClick={() => setIsOpen(true)}>
|
||||||
<span>
|
<span>
|
||||||
<BiFilterAlt className="addition_select_icon" />
|
<BiFilterAlt className="addition_select_icon" />
|
||||||
|
|
@ -53,6 +57,9 @@ const FilterLayout = ({
|
||||||
</span>
|
</span>
|
||||||
<MdKeyboardArrowDown />
|
<MdKeyboardArrowDown />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span>
|
<span>
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,6 @@ const FormikFormModel: React.FC<FormikFormProps> = ({
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpen === "") {
|
if (isOpen === "") {
|
||||||
formik.setErrors({});
|
formik.setErrors({});
|
||||||
}
|
|
||||||
if (isOpen === "isSuccess") {
|
|
||||||
formik.setErrors({});
|
|
||||||
formik.resetForm();
|
formik.resetForm();
|
||||||
}
|
}
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ import {
|
||||||
import ActionButtons from "../../../Components/Table/ActionButtons";
|
import ActionButtons from "../../../Components/Table/ActionButtons";
|
||||||
import ColumnsImage from "../../../Components/Columns/ColumnsImage";
|
import ColumnsImage from "../../../Components/Columns/ColumnsImage";
|
||||||
import { Grade } from "../../../types/Grade";
|
import { Grade } from "../../../types/Grade";
|
||||||
|
import { CiImageOff } from "react-icons/ci";
|
||||||
|
import { isValidImage } from "../../../utils/isValidImage";
|
||||||
|
|
||||||
export const useColumns = () => {
|
export const useColumns = () => {
|
||||||
const { handel_open_model } = useModalHandler();
|
const { handel_open_model } = useModalHandler();
|
||||||
|
|
@ -59,20 +61,11 @@ export const useColumns = () => {
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (_text: any, record: Grade) => {
|
render: (_text: any, record: Grade) => {
|
||||||
let str = record?.icon;
|
let str = record?.icon;
|
||||||
return <ColumnsImage src={str} />;
|
|
||||||
|
return <ColumnsImage src={str}/> ;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// canAddGrade ? (
|
|
||||||
// <button
|
|
||||||
// onClick={() => handel_open_model(ModalEnum?.GRADE_ADD)}
|
|
||||||
// className="add_button"
|
|
||||||
// >
|
|
||||||
// {t("practical.add")} {t("models.grade")} <FaPlus />
|
|
||||||
// </button>
|
|
||||||
// ) : (
|
|
||||||
// ""
|
|
||||||
// ),
|
|
||||||
|
|
||||||
title: t("columns.procedure"),
|
title: t("columns.procedure"),
|
||||||
key: "actions",
|
key: "actions",
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,143 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import ValidationField from "../../../Components/ValidationField/ValidationField";
|
import ValidationField from "../../../Components/ValidationField/ValidationField";
|
||||||
import { Col, Row } from "reactstrap";
|
import { Col, Row } from "reactstrap";
|
||||||
import useFormatDataToSelect from "../../../utils/useFormatDataToSelect";
|
import { useFormikContext } from "formik";
|
||||||
|
import { useGetAllGrade } from "../../../api/grade";
|
||||||
|
import { useValidationValidationParamState } from "../../../Components/ValidationField/state/ValidationValidationParamState";
|
||||||
|
import { useGetAllUnit } from "../../../api/unit";
|
||||||
|
import { useGetAllSubject } from "../../../api/subject";
|
||||||
|
import { useGetAllLesson } from "../../../api/lesson";
|
||||||
|
|
||||||
const FilterForm = () => {
|
const FilterForm = () => {
|
||||||
const yesNoArray = [
|
|
||||||
{ id: "لا", name: "لا" },
|
const { ValidationParamState } = useValidationValidationParamState();
|
||||||
{ id: "نعم", name: "نعم" },
|
const {
|
||||||
];
|
GradeName, GradeCurrentPage,
|
||||||
|
SubjectName, SubjectCurrentPage,
|
||||||
|
UnitName, UnitCurrentPage,
|
||||||
|
LessonName, LessonCurrentPage
|
||||||
|
|
||||||
|
|
||||||
|
} = ValidationParamState;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const { data: Grade, isLoading: isLoadingGrade } = useGetAllGrade({
|
||||||
|
name: GradeName,
|
||||||
|
page: GradeCurrentPage
|
||||||
|
});
|
||||||
|
const GradeOption = Grade?.data ?? []
|
||||||
|
const canChangeGradePage = !!Grade?.links?.next;
|
||||||
|
const GradePage = Grade?.meta?.currentPage;
|
||||||
|
|
||||||
|
|
||||||
|
/// subject_id
|
||||||
|
const { data: Subject, isLoading: isLoadingSubject } = useGetAllSubject({
|
||||||
|
name: SubjectName,
|
||||||
|
page: SubjectCurrentPage
|
||||||
|
});
|
||||||
|
const SubjectOption = Subject?.data ?? []
|
||||||
|
const canChangeSubjectPage = !!Subject?.links?.next;
|
||||||
|
const SubjectPage = Subject?.meta?.currentPage;
|
||||||
|
|
||||||
|
/// unit_id
|
||||||
|
const { data: Unit, isLoading: isLoadingUnit } = useGetAllUnit({
|
||||||
|
name: UnitName,
|
||||||
|
page: UnitCurrentPage
|
||||||
|
});
|
||||||
|
const UnitOption = Unit?.data ?? []
|
||||||
|
const canChangeUnitPage = !!Unit?.links?.next;
|
||||||
|
const UnitPage = Unit?.meta?.currentPage;
|
||||||
|
|
||||||
|
/// lessonsIds
|
||||||
|
const { data: Lesson, isLoading: isLoadingLesson } = useGetAllLesson({
|
||||||
|
name: LessonName,
|
||||||
|
page: LessonCurrentPage
|
||||||
|
});
|
||||||
|
const LessonOption = Lesson?.data ?? []
|
||||||
|
const canChangeLessonPage = !!Lesson?.links?.next;
|
||||||
|
const LessonPage = Lesson?.meta?.currentPage;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
|
{/*
|
||||||
|
grade_id
|
||||||
|
*/}
|
||||||
<ValidationField
|
<ValidationField
|
||||||
placeholder="content"
|
searchBy="GradeName"
|
||||||
label="content"
|
name="grade_id"
|
||||||
name="content"
|
label="grade"
|
||||||
|
type="Search"
|
||||||
|
option={GradeOption}
|
||||||
|
isLoading={isLoadingGrade}
|
||||||
|
canChangePage={canChangeGradePage}
|
||||||
|
PageName={"GradeCurrentPage"}
|
||||||
|
page={GradePage}
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
{/*
|
||||||
|
subject_id
|
||||||
|
*/}
|
||||||
|
|
||||||
|
<ValidationField
|
||||||
|
searchBy="SubjectName"
|
||||||
|
name="subject_id"
|
||||||
|
label="subject"
|
||||||
|
type="Search"
|
||||||
|
option={SubjectOption}
|
||||||
|
isLoading={isLoadingSubject}
|
||||||
|
canChangePage={canChangeSubjectPage}
|
||||||
|
PageName={"SubjectCurrentPage"}
|
||||||
|
page={SubjectPage}
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
{/*
|
||||||
|
unit_id
|
||||||
|
*/}
|
||||||
|
|
||||||
|
<ValidationField
|
||||||
|
searchBy="UnitName"
|
||||||
|
name="unit_id"
|
||||||
|
label="unit"
|
||||||
|
type="Search"
|
||||||
|
option={UnitOption}
|
||||||
|
isLoading={isLoadingUnit}
|
||||||
|
canChangePage={canChangeUnitPage}
|
||||||
|
PageName={"UnitCurrentPage"}
|
||||||
|
page={UnitPage}
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
{/*
|
||||||
|
lessonsIds
|
||||||
|
*/}
|
||||||
|
|
||||||
|
<ValidationField
|
||||||
|
searchBy="LessonName"
|
||||||
|
name="lessonsIds"
|
||||||
|
label="lesson"
|
||||||
|
type="Search"
|
||||||
|
option={LessonOption}
|
||||||
|
isMulti
|
||||||
|
isLoading={isLoadingLesson}
|
||||||
|
canChangePage={canChangeLessonPage}
|
||||||
|
PageName={"LessonCurrentPage"}
|
||||||
|
page={LessonPage}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
{/* <ValidationField type="Select" option={yesNoArray} placeholder="isBase" label="isBase" name="isBase" /> */}
|
|
||||||
</Col>
|
</Col>
|
||||||
{/* <Col>
|
|
||||||
<ValidationField type="Select" option={yesNoArray} placeholder="canAnswersBeShuffled" label="canAnswersBeShuffled" name="canAnswersBeShuffled" />
|
|
||||||
</Col> */}
|
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,8 @@ const TableHeader = () => {
|
||||||
<FilterLayout
|
<FilterLayout
|
||||||
sub_children={<FilterForm />}
|
sub_children={<FilterForm />}
|
||||||
filterTitle={` ${unitName} (${LessonName}) `}
|
filterTitle={` ${unitName} (${LessonName}) `}
|
||||||
|
search_by="content"
|
||||||
|
haveFilter={false}
|
||||||
/>
|
/>
|
||||||
<Table />
|
<Table />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,18 @@ import { useGetAllQuestion } from "../../../api/Question";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { ParamsEnum } from "../../../enums/params";
|
import { ParamsEnum } from "../../../enums/params";
|
||||||
import { useFilterState } from "../../../Components/Utils/Filter/FilterState";
|
import { useFilterState } from "../../../Components/Utils/Filter/FilterState";
|
||||||
|
import { useFilterStateState } from "../../../zustand/Filter";
|
||||||
|
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
const { lesson_id } = useParams<ParamsEnum>();
|
const { lesson_id } = useParams<ParamsEnum>();
|
||||||
const { filterState } = useFilterState();
|
const { filterState } = useFilterState();
|
||||||
|
const { setFilter,Filter } = useFilterStateState();
|
||||||
|
|
||||||
const response = useGetAllQuestion({
|
const response = useGetAllQuestion({
|
||||||
lessonsIds: [lesson_id],
|
lessonsIds: [lesson_id],
|
||||||
pagination: true,
|
pagination: true,
|
||||||
...filterState,
|
...filterState,
|
||||||
|
content:Filter?.content
|
||||||
});
|
});
|
||||||
return <DataTable response={response} useColumns={useColumns} />;
|
return <DataTable response={response} useColumns={useColumns} />;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import {
|
||||||
} from "../../../../utils/hasAbilityFn";
|
} from "../../../../utils/hasAbilityFn";
|
||||||
import { ABILITIES_ENUM } from "../../../../enums/abilities";
|
import { ABILITIES_ENUM } from "../../../../enums/abilities";
|
||||||
import { Subject } from "../../../../types/Subject";
|
import { Subject } from "../../../../types/Subject";
|
||||||
|
import { CiImageOff } from "react-icons/ci";
|
||||||
|
|
||||||
export const useColumns = () => {
|
export const useColumns = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
@ -54,7 +55,7 @@ export const useColumns = () => {
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (row: Subject, record) => {
|
render: (row: Subject, record) => {
|
||||||
let str = record.icon;
|
let str = record.icon;
|
||||||
return <ColumnsImage src={str} />;
|
return <ColumnsImage src={str}/> ;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
9
src/utils/isValidImage.ts
Normal file
9
src/utils/isValidImage.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
export const isValidImage = (url: string): Promise<boolean> => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const img = new Image();
|
||||||
|
img.src = url;
|
||||||
|
|
||||||
|
img.onload = () => resolve(true); // Image loaded successfully
|
||||||
|
img.onerror = () => resolve(false); // Error loading image
|
||||||
|
});
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user