Skip to content

Commit 0a9264b

Browse files
authored
Merge pull request #85 from iranpsc/fix/packagePart2
2 parents 5a00790 + 1290caa commit 0a9264b

49 files changed

Lines changed: 10802 additions & 27917 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

package-lock.json

Lines changed: 10368 additions & 26884 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"@deck.gl/mesh-layers": "^9.0.0",
2222
"@emotion/css": "^11.13.0",
2323
"@persian-tools/persian-tools": "^3.4.1",
24+
"@react-spring/web": "10.0.3",
2425
"@react-three/drei": "^9.122.0",
2526
"@react-three/fiber": "^8.18.0",
2627
"@sentry/react": "^8.53.0",
@@ -37,23 +38,21 @@
3738
"compressorjs": "^1.2.1",
3839
"deck.gl-leaflet": "^1.2.1",
3940
"dompurify": "^3.3.0",
40-
"drei": "^2.2.21",
41-
"esbuild": "^0.19.2",
41+
"esbuild": "^0.27.3",
4242
"i18next": "^23.15.1",
4343
"i18next-chained-backend": "^4.6.2",
4444
"i18next-http-backend": "^2.6.1",
4545
"i18next-localstorage-backend": "^4.2.0",
4646
"jalali-moment": "^3.3.11",
47-
"jsonpath": "^1.2.1",
4847
"keen-slider": "^6.8.6",
4948
"laravel-echo": "^1.15.0",
5049
"leaflet": "^1.9.4",
51-
"lodash": "^4.17.21",
5250
"lottie-react": "^2.4.0",
5351
"mapbox-gl": "^3.9.4",
5452
"maplibre-gl": "^3.6.2",
5553
"moment-jalaali": "^0.10.4",
5654
"pusher-js": "^8.0.1",
55+
"quill": "^2.0.3",
5756
"react": "^18.2.0",
5857
"react-confetti-explosion": "^2.1.2",
5958
"react-countdown": "^2.3.5",
@@ -71,11 +70,9 @@
7170
"react-quill": "^2.0.0",
7271
"react-rnd": "^10.4.12",
7372
"react-router-dom": "^6.6.1",
74-
"react-scripts": "^5.0.1",
7573
"react-share-kit": "^1.1.0",
7674
"react-simple-wysiwyg": "^3.1.1",
7775
"react-spinners": "^0.13.7",
78-
"react-spring": "^9.7.2",
7976
"react-three-map": "^0.7.2",
8077
"react-toastify": "^10.0.5",
8178
"react-tooltip": "^5.28.1",
@@ -87,9 +84,8 @@
8784
"slate-history": "^0.100.0",
8885
"slate-react": "^0.108.0",
8986
"styled-components": "^5.3.6",
90-
"swiper": "^11.1.9",
87+
"swiper": "^12.1.2",
9188
"three": "^0.159.0",
92-
"vite-plugin-svgr": "^3.2.0",
9389
"web-vitals": "^2.1.4"
9490
},
9591
"devDependencies": {
@@ -105,7 +101,8 @@
105101
"eslint-plugin-react-hooks": "^4.6.0",
106102
"eslint-plugin-react-refresh": "^0.3.4",
107103
"standard-version": "^9.5.0",
108-
"vite": "^4.3.2"
104+
"vite": "^4.3.2",
105+
"vite-plugin-svgr": "^3.3.0"
109106
},
110107
"engines": {
111108
"node": "16.x"

src/App.jsx

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { useLayoutEffect } from "react";
22
import { BrowserRouter } from "react-router-dom"; // Import useNavigate
33
import { Toaster } from "react-hot-toast";
44
import "./App.css";
5-
import "react-quill/dist/quill.snow.css";
65
import "./i18n/i18n.js";
76
import Echo from "laravel-echo";
87
import Pusher from "pusher-js";
@@ -18,7 +17,6 @@ import Routers from "./layouts/map/Routers.jsx";
1817
import { LanguageProvider } from "./services/reducers/LanguageContext.jsx";
1918
import { LoaderProvider } from "./services/reducers/LoaderProvider.jsx";
2019
import RotateDevice from "./components/RotateDevice";
21-
import Error410Modal from "./components/Error410Modal";
2220
import { useAppHeight } from "./hooks/useAppHeight.js";
2321
import { ScrollDirectionProvider } from "./services/reducers/ScrollDirectionContext.jsx";
2422
function App() {
@@ -39,42 +37,41 @@ function App() {
3937
});
4038
}, []);
4139

42-
return (<LanguageProvider>
43-
44-
<BrowserRouter>
45-
<ScrollDirectionProvider>
46-
<LoaderProvider>
47-
<MapProvider>
48-
<ThemeProviderContext>
49-
<UserProvider>
50-
<WalletProvider>
51-
<FollowProvider>
52-
<SelectedEnvironmentProvider>
53-
<MapContextProvider>
54-
<AlertProvider>
55-
<RotateDevice />
56-
<Routers />
57-
58-
<Error410Modal />
59-
<Toaster
60-
containerStyle={{
61-
zIndex: 100000,
62-
marginBottom: 48,
63-
}}
64-
position="bottom-right"
65-
/>
66-
</AlertProvider>
67-
</MapContextProvider>
68-
</SelectedEnvironmentProvider>
69-
</FollowProvider>
70-
</WalletProvider>
71-
</UserProvider>
72-
</ThemeProviderContext>
73-
</MapProvider>
74-
</LoaderProvider>
75-
</ScrollDirectionProvider>
76-
</BrowserRouter> </LanguageProvider>
40+
return (
41+
<LanguageProvider>
42+
<BrowserRouter>
43+
<ScrollDirectionProvider>
44+
<LoaderProvider>
45+
<MapProvider>
46+
<ThemeProviderContext>
47+
<UserProvider>
48+
<WalletProvider>
49+
<FollowProvider>
50+
<SelectedEnvironmentProvider>
51+
<MapContextProvider>
52+
<AlertProvider>
53+
<RotateDevice />
54+
<Routers />
7755

56+
<Toaster
57+
containerStyle={{
58+
zIndex: 100000,
59+
marginBottom: 48,
60+
}}
61+
position="bottom-right"
62+
/>
63+
</AlertProvider>
64+
</MapContextProvider>
65+
</SelectedEnvironmentProvider>
66+
</FollowProvider>
67+
</WalletProvider>
68+
</UserProvider>
69+
</ThemeProviderContext>
70+
</MapProvider>
71+
</LoaderProvider>
72+
</ScrollDirectionProvider>
73+
</BrowserRouter>{" "}
74+
</LanguageProvider>
7875
);
7976
}
8077

src/components/Common/CustomEditor.jsx

Lines changed: 151 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,137 @@ import ReactQuill from "react-quill";
44
import { CiEdit } from "react-icons/ci";
55
import {
66
convertToPersian,
7+
SanitizeHTML,
78
getFieldTranslationByNames,
89
} from "../../services/Utility";
9-
import {
10-
EditorContainer as StyledEditorContainer,
11-
Label,
12-
Char,
13-
formats,
14-
modulesWithoutImage,
15-
} from "../editorContainerStyle";
10+
import styled from "styled-components";
11+
12+
const EditorContainer = styled.div`
13+
background-color: ${(props) =>
14+
props.theme.colors.newColors.otherColors.inputBg};
15+
border-radius: 5px;
16+
overflow: hidden;
17+
color: white;
18+
margin: 10px auto;
19+
height: 212px;
20+
border: ${({ border }) => (border ? "1px solid gray" : "none")};
21+
.ql-toolbar {
22+
background-color: ${(props) =>
23+
props.theme.colors.newColors.otherColors.inputBg};
24+
border: none;
25+
border-bottom: 1px solid gray;
26+
}
27+
28+
.ql-container {
29+
background-color: ${(props) =>
30+
props.theme.colors.newColors.otherColors.inputBg};
31+
color: ${(props) => props.theme.colors.newColors.shades.title};
32+
border: none;
33+
overflow: auto;
34+
max-height: 150px;
35+
}
36+
37+
&& .ql-editor {
38+
min-height: 150px;
39+
text-align: unset;
40+
font-size: 18px !important;
41+
line-height: 1.6;
42+
-webkit-text-size-adjust: 100%;
43+
font-family: "AzarMehr" !important;
44+
}
45+
46+
/* placeholder */
47+
&& .ql-editor::before {
48+
font-size: inherit !important;
49+
color: #888;
50+
opacity: 0.7;
51+
font-family: "AzarMehr" !important;
52+
}
53+
54+
.ql-toolbar .ql-picker {
55+
color: white;
56+
}
57+
58+
.ql-toolbar .ql-stroke {
59+
stroke: ${(props) => props.theme.colors.newColors.shades.title};
60+
}
61+
62+
.ql-toolbar .ql-fill {
63+
fill: ${(props) => props.theme.colors.newColors.shades.title};
64+
}
65+
66+
.ql-toolbar .ql-picker-options {
67+
border: 1px solid #555;
68+
}
69+
70+
@media (max-width: 700px) {
71+
&& .ql-editor {
72+
font-size: 15px !important;
73+
-webkit-text-size-adjust: 100%;
74+
}
75+
}
76+
`;
77+
78+
const Label = styled.h2`
79+
color: ${(props) => props.theme.colors.newColors.shades.title};
80+
display: block;
81+
margin-bottom: 10px;
82+
font-weight: 500;
83+
font-size: 16px;
84+
margin-top: 20px;
85+
`;
86+
87+
const Char = styled.div`
88+
display: flex;
89+
justify-content: end;
90+
align-items: center;
91+
gap: 5px;
92+
svg {
93+
color: ${({ isOverLimit, theme }) =>
94+
isOverLimit ? "red" : theme.colors.newColors.shades.title};
95+
}
96+
97+
span {
98+
color: ${({ isOverLimit }) => (isOverLimit ? "red" : "#a0a0ab")};
99+
font-size: 13px;
100+
font-weight: 400;
101+
}
102+
`;
103+
const formats = [
104+
"size",
105+
"bold",
106+
"italic",
107+
"underline",
108+
"strike",
109+
"blockquote",
110+
"list",
111+
"bullet",
112+
"indent",
113+
"link",
114+
"code-block",
115+
"align",
116+
];
117+
118+
const getModules = (img = false) => {
119+
const toolbar = [
120+
["bold", "italic", "underline", "strike", "blockquote"],
121+
[
122+
{ list: "ordered" },
123+
{ list: "bullet" },
124+
{ indent: "-1" },
125+
{ indent: "+1" },
126+
],
127+
["link", "code-block"], // دکمه تصویر به صورت داینامیک اضافه می‌شود
128+
[{ align: [] }],
129+
];
130+
131+
if (img) {
132+
// اضافه کردن دکمه image در صورت فعال بودن پراپ
133+
toolbar[2].splice(1, 0, "image"); // دکمه image بعد از link اضافه می‌شود
134+
}
135+
136+
return { toolbar };
137+
};
16138

17139
/**
18140
* Reusable RichTextEditor with strict char limit
@@ -33,28 +155,28 @@ const CustomEditor = ({
33155
showIcon = true,
34156
placeholder = "",
35157
border = false,
158+
img = false,
36159
}) => {
37160
const [content, setContent] = useState(value);
38161

39162
useEffect(() => {
40163
setContent(value);
41164
}, [value]);
42165
const handleChange = (val, delta, source, editor) => {
43-
// طول واقعی متن بدون html
44-
const text = editor.getText(); // این متن plain text است
166+
const text = editor.getText();
45167
let newValue = val;
46168

47169
if (text.length - 1 > charLimit) {
48-
// -1 چون editor یه \n اضافه می‌کنه
49170
const allowedText = text.slice(0, charLimit);
50-
// جایگزینی متن editor با محدودیت
51171
const quill = editor;
52-
quill.deleteText(charLimit, text.length); // بقیه رو حذف می‌کنه
172+
quill.deleteText(charLimit, text.length);
53173
newValue = quill.root.innerHTML;
54174
}
55175

56-
setContent(newValue);
57-
onChange?.(newValue);
176+
const safeValue = SanitizeHTML(newValue);
177+
178+
setContent(safeValue);
179+
onChange?.(safeValue);
58180
};
59181

60182
const handleKeyDown = (event) => {
@@ -70,16 +192,22 @@ const CustomEditor = ({
70192
event.preventDefault();
71193
}
72194
};
73-
74195
const handlePaste = (event) => {
75196
event.preventDefault();
197+
76198
const paste = event.clipboardData.getData("text");
77199
const remaining = charLimit - content.length;
78-
if (remaining <= 0) return; // هیچ چیزی اضافه نشود
79-
const toPaste = paste.slice(0, remaining);
80-
const newValue = content + toPaste;
81-
setContent(newValue);
82-
onChange?.(newValue);
200+
201+
if (paste.length > remaining) {
202+
return;
203+
}
204+
205+
const newValue = content + paste;
206+
207+
const safeValue = SanitizeHTML(newValue);
208+
209+
setContent(safeValue);
210+
onChange?.(safeValue);
83211
};
84212

85213
const remainingChars = charLimit - content.length;
@@ -88,17 +216,17 @@ const CustomEditor = ({
88216
return (
89217
<div>
90218
{label && <Label>{label}</Label>}
91-
<StyledEditorContainer border={border}>
219+
<EditorContainer border={border}>
92220
<ReactQuill
93221
value={content}
94222
onChange={handleChange}
95223
onKeyDown={handleKeyDown}
96224
onPaste={handlePaste}
97-
modules={modulesWithoutImage}
225+
modules={getModules(img)}
98226
formats={formats}
99227
placeholder={placeholder}
100228
/>
101-
</StyledEditorContainer>
229+
</EditorContainer>
102230
<Char isOverLimit={isOverLimit}>
103231
<span>
104232
{convertToPersian(remainingChars)} {getFieldTranslationByNames("530")}

0 commit comments

Comments
 (0)