fix image
This commit is contained in:
parent
e8e50d0526
commit
d6c8ff6468
|
|
@ -1,43 +1,33 @@
|
|||
import {
|
||||
DownloadOutlined,
|
||||
RotateLeftOutlined,
|
||||
RotateRightOutlined,
|
||||
SwapOutlined,
|
||||
ZoomInOutlined,
|
||||
ZoomOutOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import { Image, Space } from "antd";
|
||||
import useImageError from "../../Hooks/useImageError";
|
||||
import { ErrorImage } from "../../Layout/app/Const";
|
||||
import { CiImageOff } from "react-icons/ci"; // Assuming you're using this icon from react-icons
|
||||
|
||||
const ColumnsImage = ({ src }: any) => {
|
||||
const imageUrl = src || ErrorImage;
|
||||
const [hasError, setHasError] = useState(false); // Track if the image has an error
|
||||
|
||||
const handleError = useImageError;
|
||||
// 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();
|
||||
});
|
||||
};
|
||||
const imageUrl = src;
|
||||
|
||||
if (hasError) {
|
||||
// If there is an error, display the fallback icon
|
||||
return <CiImageOff />;
|
||||
}
|
||||
if(!imageUrl){
|
||||
return <CiImageOff />;
|
||||
}
|
||||
return (
|
||||
<Image
|
||||
width={45}
|
||||
height={45}
|
||||
src={imageUrl}
|
||||
className="p-1 mb-1 columnImage "
|
||||
className="p-1 mb-1 columnImage"
|
||||
onError={() => setHasError(true)} // Triggered when image fails to load
|
||||
preview={{
|
||||
toolbarRender: (
|
||||
_,
|
||||
|
|
@ -54,7 +44,6 @@ const ColumnsImage = ({ src }: any) => {
|
|||
},
|
||||
) => (
|
||||
<Space size={12} className="toolbar-wrapper">
|
||||
{/* <DownloadOutlined onClick={onDownload} /> */}
|
||||
<SwapOutlined rotate={90} onClick={onFlipY} />
|
||||
<SwapOutlined onClick={onFlipX} />
|
||||
<RotateLeftOutlined onClick={onRotateLeft} />
|
||||
|
|
@ -64,19 +53,8 @@ const ColumnsImage = ({ src }: any) => {
|
|||
</Space>
|
||||
),
|
||||
}}
|
||||
onError={handleError}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default ColumnsImage;
|
||||
|
||||
// {
|
||||
// name: t("image"),
|
||||
// center: "true",
|
||||
// cell: (row: any) => {
|
||||
// return (
|
||||
// <ColumnsImage src={row?.image} />
|
||||
// )
|
||||
// }
|
||||
// },
|
||||
|
|
|
|||
|
|
@ -15,12 +15,14 @@ const FilterLayout = ({
|
|||
filterTitle,
|
||||
sub_children,
|
||||
search_by = "name",
|
||||
width = "500px"
|
||||
width = "500px",
|
||||
haveFilter=true
|
||||
}: {
|
||||
filterTitle: string;
|
||||
sub_children: any;
|
||||
search_by?:string
|
||||
width?:string
|
||||
haveFilter?:boolean
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const translateArray = translateOptions(search_array, t);
|
||||
|
|
@ -46,13 +48,18 @@ const FilterLayout = ({
|
|||
<div className="model_sub_children">{sub_children}</div>
|
||||
<FilterSubmit />
|
||||
</FilterBody>
|
||||
<div className="filter_button" onClick={() => setIsOpen(true)}>
|
||||
{haveFilter &&
|
||||
|
||||
<div className="filter_button" onClick={() => setIsOpen(true)}>
|
||||
<span>
|
||||
<BiFilterAlt className="addition_select_icon" />
|
||||
{t("header.filter")}
|
||||
</span>
|
||||
<MdKeyboardArrowDown />
|
||||
</div>
|
||||
|
||||
}
|
||||
|
||||
</span>
|
||||
|
||||
<span>
|
||||
|
|
|
|||
|
|
@ -35,9 +35,6 @@ const FormikFormModel: React.FC<FormikFormProps> = ({
|
|||
useEffect(() => {
|
||||
if (isOpen === "") {
|
||||
formik.setErrors({});
|
||||
}
|
||||
if (isOpen === "isSuccess") {
|
||||
formik.setErrors({});
|
||||
formik.resetForm();
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ import {
|
|||
import ActionButtons from "../../../Components/Table/ActionButtons";
|
||||
import ColumnsImage from "../../../Components/Columns/ColumnsImage";
|
||||
import { Grade } from "../../../types/Grade";
|
||||
import { CiImageOff } from "react-icons/ci";
|
||||
import { isValidImage } from "../../../utils/isValidImage";
|
||||
|
||||
export const useColumns = () => {
|
||||
const { handel_open_model } = useModalHandler();
|
||||
|
|
@ -59,20 +61,11 @@ export const useColumns = () => {
|
|||
align: "center",
|
||||
render: (_text: any, record: Grade) => {
|
||||
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"),
|
||||
key: "actions",
|
||||
|
|
|
|||
|
|
@ -1,27 +1,143 @@
|
|||
import React from "react";
|
||||
import ValidationField from "../../../Components/ValidationField/ValidationField";
|
||||
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 yesNoArray = [
|
||||
{ id: "لا", name: "لا" },
|
||||
{ id: "نعم", name: "نعم" },
|
||||
];
|
||||
|
||||
const { ValidationParamState } = useValidationValidationParamState();
|
||||
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 (
|
||||
<div>
|
||||
<Row>
|
||||
<Col>
|
||||
<ValidationField
|
||||
placeholder="content"
|
||||
label="content"
|
||||
name="content"
|
||||
/>
|
||||
{/* <ValidationField type="Select" option={yesNoArray} placeholder="isBase" label="isBase" name="isBase" /> */}
|
||||
{/*
|
||||
grade_id
|
||||
*/}
|
||||
<ValidationField
|
||||
searchBy="GradeName"
|
||||
name="grade_id"
|
||||
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}
|
||||
|
||||
/>
|
||||
</Col>
|
||||
{/* <Col>
|
||||
<ValidationField type="Select" option={yesNoArray} placeholder="canAnswersBeShuffled" label="canAnswersBeShuffled" name="canAnswersBeShuffled" />
|
||||
</Col> */}
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -65,6 +65,8 @@ const TableHeader = () => {
|
|||
<FilterLayout
|
||||
sub_children={<FilterForm />}
|
||||
filterTitle={` ${unitName} (${LessonName}) `}
|
||||
search_by="content"
|
||||
haveFilter={false}
|
||||
/>
|
||||
<Table />
|
||||
</Suspense>
|
||||
|
|
|
|||
|
|
@ -5,15 +5,18 @@ import { useGetAllQuestion } from "../../../api/Question";
|
|||
import { useParams } from "react-router-dom";
|
||||
import { ParamsEnum } from "../../../enums/params";
|
||||
import { useFilterState } from "../../../Components/Utils/Filter/FilterState";
|
||||
import { useFilterStateState } from "../../../zustand/Filter";
|
||||
|
||||
const App: React.FC = () => {
|
||||
const { lesson_id } = useParams<ParamsEnum>();
|
||||
const { filterState } = useFilterState();
|
||||
const { setFilter,Filter } = useFilterStateState();
|
||||
|
||||
const response = useGetAllQuestion({
|
||||
lessonsIds: [lesson_id],
|
||||
pagination: true,
|
||||
...filterState,
|
||||
content:Filter?.content
|
||||
});
|
||||
return <DataTable response={response} useColumns={useColumns} />;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import {
|
|||
} from "../../../../utils/hasAbilityFn";
|
||||
import { ABILITIES_ENUM } from "../../../../enums/abilities";
|
||||
import { Subject } from "../../../../types/Subject";
|
||||
import { CiImageOff } from "react-icons/ci";
|
||||
|
||||
export const useColumns = () => {
|
||||
const navigate = useNavigate();
|
||||
|
|
@ -54,7 +55,7 @@ export const useColumns = () => {
|
|||
align: "center",
|
||||
render: (row: Subject, record) => {
|
||||
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