imio.smartweb.core 1.4.3__py3-none-any.whl → 1.4.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. imio/smartweb/core/browser/configure.zcml +8 -0
  2. imio/smartweb/core/browser/controlpanel_siteadmin.py +142 -0
  3. imio/smartweb/core/browser/sitemap.py +1 -1
  4. imio/smartweb/core/browser/static/src/view.js +9 -2
  5. imio/smartweb/core/contents/pages/procedure/content.py +8 -0
  6. imio/smartweb/core/contents/rest/directory/endpoint.py +1 -1
  7. imio/smartweb/core/contents/sections/events/view.py +1 -1
  8. imio/smartweb/core/permissions.zcml +6 -0
  9. imio/smartweb/core/profiles/default/controlpanel.xml +12 -0
  10. imio/smartweb/core/profiles/default/metadata.xml +1 -1
  11. imio/smartweb/core/profiles/default/registry/smartweb.xml +3 -0
  12. imio/smartweb/core/profiles/default/rolemap.xml +5 -0
  13. imio/smartweb/core/profiles/default/taxonomies/procedure_category.xml +9 -0
  14. imio/smartweb/core/profiles/default/types/imio.smartweb.Page.xml +2 -1
  15. imio/smartweb/core/profiles/default/types/imio.smartweb.PortalPage.xml +1 -0
  16. imio/smartweb/core/setuphandlers.py +2 -0
  17. imio/smartweb/core/upgrades/configure.zcml +41 -1
  18. imio/smartweb/core/upgrades/profiles/1068_to_1069/controlpanel.xml +26 -0
  19. imio/smartweb/core/upgrades/profiles/1068_to_1069/registry.xml +9 -0
  20. imio/smartweb/core/upgrades/profiles/1068_to_1069/rolemap.xml +11 -0
  21. imio/smartweb/core/upgrades/profiles/1069_to_1070/taxonomies/procedure_category.cfg +9 -0
  22. imio/smartweb/core/upgrades/profiles/1069_to_1070/taxonomies/procedure_category.xml +121 -0
  23. imio/smartweb/core/upgrades/upgrades.py +7 -1
  24. imio/smartweb/core/utils.py +38 -0
  25. imio/smartweb/core/viewlets/procedure.pt +1 -0
  26. imio/smartweb/core/viewlets/procedure.py +14 -0
  27. imio/smartweb/core/vocabularies.py +28 -2
  28. imio/smartweb/core/vocabularies.zcml +6 -0
  29. imio/smartweb/core/webcomponents/build/css/251.smartweb-webcomponents-compiled.css +1 -0
  30. imio/smartweb/core/webcomponents/build/css/373.smartweb-webcomponents-compiled.css +1 -1
  31. imio/smartweb/core/webcomponents/build/css/666.smartweb-webcomponents-compiled.css +1 -1
  32. imio/smartweb/core/webcomponents/build/css/700.smartweb-webcomponents-compiled.css +1 -0
  33. imio/smartweb/core/webcomponents/build/js/141.smartweb-webcomponents-compiled.js +1 -1
  34. imio/smartweb/core/webcomponents/build/js/141.smartweb-webcomponents-compiled.js.LICENSE.txt +3 -3
  35. imio/smartweb/core/webcomponents/build/js/15.smartweb-webcomponents-compiled.js +2 -0
  36. imio/smartweb/core/webcomponents/build/js/21.smartweb-webcomponents-compiled.js +1 -1
  37. imio/smartweb/core/webcomponents/build/js/218.smartweb-webcomponents-compiled.js +1 -1
  38. imio/smartweb/core/webcomponents/build/js/251.smartweb-webcomponents-compiled.js +1 -0
  39. imio/smartweb/core/webcomponents/build/js/373.smartweb-webcomponents-compiled.js +1 -1
  40. imio/smartweb/core/webcomponents/build/js/666.smartweb-webcomponents-compiled.js +1 -1
  41. imio/smartweb/core/webcomponents/build/js/700.smartweb-webcomponents-compiled.js +1 -0
  42. imio/smartweb/core/webcomponents/build/js/824.smartweb-webcomponents-compiled.js +1 -1
  43. imio/smartweb/core/webcomponents/build/js/919.smartweb-webcomponents-compiled.js +1 -1
  44. imio/smartweb/core/webcomponents/build/js/922.smartweb-webcomponents-compiled.js +1 -1
  45. imio/smartweb/core/webcomponents/build/js/963.smartweb-webcomponents-compiled.js +1 -1
  46. imio/smartweb/core/webcomponents/build/js/smartweb-webcomponents-compiled.js +1 -1
  47. imio/smartweb/core/webcomponents/package.json +1 -1
  48. imio/smartweb/core/webcomponents/src/components/Annuaire/Annuaire.scss +32 -1
  49. imio/smartweb/core/webcomponents/src/components/Annuaire/Filters/Filter.jsx +118 -70
  50. imio/smartweb/core/webcomponents/src/components/Filters/MainFilter.scss +4 -8
  51. imio/smartweb/core/webcomponents/src/components/Filters/TaxonomyFilter.jsx +167 -85
  52. imio/smartweb/core/webcomponents/src/components/Filters/TaxonomyFilter.scss +44 -15
  53. imio/smartweb/core/webcomponents/src/components/News/News.scss +0 -1
  54. imio/smartweb/core/webcomponents/src/components/News/NewsContent/NewsContent.jsx +20 -11
  55. {imio_smartweb_core-1.4.3.dist-info → imio_smartweb_core-1.4.5.dist-info}/METADATA +27 -1
  56. {imio_smartweb_core-1.4.3.dist-info → imio_smartweb_core-1.4.5.dist-info}/RECORD +63 -58
  57. {imio_smartweb_core-1.4.3.dist-info → imio_smartweb_core-1.4.5.dist-info}/WHEEL +1 -1
  58. imio/smartweb/core/webcomponents/build/css/420.smartweb-webcomponents-compiled.css +0 -1
  59. imio/smartweb/core/webcomponents/build/css/486.smartweb-webcomponents-compiled.css +0 -1
  60. imio/smartweb/core/webcomponents/build/css/884.smartweb-webcomponents-compiled.css +0 -1
  61. imio/smartweb/core/webcomponents/build/js/486.smartweb-webcomponents-compiled.js +0 -1
  62. imio/smartweb/core/webcomponents/build/js/491.smartweb-webcomponents-compiled.js +0 -2
  63. imio/smartweb/core/webcomponents/build/js/884.smartweb-webcomponents-compiled.js +0 -1
  64. /imio/smartweb/core/webcomponents/build/js/{491.smartweb-webcomponents-compiled.js.LICENSE.txt → 15.smartweb-webcomponents-compiled.js.LICENSE.txt} +0 -0
  65. /imio.smartweb.core-1.4.3-py3.9-nspkg.pth → /imio.smartweb.core-1.4.5-py3.12-nspkg.pth +0 -0
  66. {imio_smartweb_core-1.4.3.dist-info → imio_smartweb_core-1.4.5.dist-info}/licenses/LICENSE.GPL +0 -0
  67. {imio_smartweb_core-1.4.3.dist-info → imio_smartweb_core-1.4.5.dist-info}/licenses/LICENSE.rst +0 -0
  68. {imio_smartweb_core-1.4.3.dist-info → imio_smartweb_core-1.4.5.dist-info}/namespace_packages.txt +0 -0
  69. {imio_smartweb_core-1.4.3.dist-info → imio_smartweb_core-1.4.5.dist-info}/top_level.txt +0 -0
@@ -72,7 +72,7 @@
72
72
  "react-markdown": "^9.0.1",
73
73
  "react-moment": "^1.1.3",
74
74
  "react-router-dom": "^6.22.3",
75
- "react-select": "^5.8.0",
75
+ "react-select": "^5.10.1",
76
76
  "react-translated": "^2.5.0",
77
77
  "react-web-component": "^2.0.2",
78
78
  "react-web-component-style-loader": "^0.1.4-alpha",
@@ -117,7 +117,7 @@ article > header {
117
117
  background-color: #000;
118
118
  background-size: cover;
119
119
  border-radius: 5px;
120
-
120
+
121
121
  &.r-item-img-placeholder {
122
122
  background-color: #f2f2f2;
123
123
  }
@@ -300,6 +300,37 @@ article > header {
300
300
  }
301
301
  }
302
302
 
303
+ .accordion-body-annuaire {
304
+ padding-top: 1rem;
305
+ display: flex;
306
+ align-items: center;
307
+ flex-wrap: wrap;
308
+ span {
309
+ font-weight: bold;
310
+ margin-right: 0.5rem;
311
+ }
312
+ .taxonomy-Filter {
313
+ width: auto;
314
+ }
315
+ }
316
+
317
+ .more-filter-btn.more-filter-btn-annuaire {
318
+ position: relative;
319
+ display: flex;
320
+ align-items: center;
321
+ gap: 0.5rem;
322
+ display: none;
323
+ @media screen and (max-width: 630px) {
324
+ display: flex;
325
+ margin-left: auto;
326
+ margin-bottom: 0.5rem;
327
+ }
328
+ }
329
+ .accordion-body-annuaire-title-full-screen {
330
+ @media screen and (max-width: 630px) {
331
+ display: none;
332
+ }
333
+ }
303
334
  // FOR BLA
304
335
 
305
336
  .r-wrapper {
@@ -1,10 +1,10 @@
1
- import React, { useEffect, useRef, useCallback, useState } from "react";
1
+ import React, { useEffect, useRef, useCallback, useState, useMemo } from "react";
2
2
  import Select from "react-select";
3
3
  import { useNavigate } from "react-router-dom";
4
4
  import useAxios from "../../../hooks/useAxios";
5
5
  import { Translator } from "react-translated";
6
6
  import queryString from "query-string";
7
- // import TaxonomyFilter from "../../Filters/TaxonomyFilter";
7
+ import TaxonomyFilter from "../../Filters/TaxonomyFilter";
8
8
  import { iam } from "./../../Filters/IamData";
9
9
  import { menuStyles, moreFilterStyles } from "./../../Filters/SelectStyles";
10
10
 
@@ -40,51 +40,68 @@ function formatData(data) {
40
40
  function Filters(props) {
41
41
  let navigate = useNavigate();
42
42
  const [inputValues, setInputValues] = useState(props.activeFilter);
43
+ const fixedParams = { b_start: 0, fullobjects: 1 };
43
44
  const [topicsFilter, setTopicsFilter] = useState([]);
44
- // const [taxonomyData, setTaxonomyData] = useState(null);
45
+ const [taxonomyData, setTaxonomyData] = useState(null);
45
46
  const [taxonomyFilter, setTaxonomyFilter] = useState(null);
46
47
  const [facilitiesFilter, setFacilitiesFilter] = useState(null);
47
48
  const [cat, setCat] = useState(false);
48
49
  const [activeComponent, setActiveComponent] = useState(null);
49
- const { response, error, isLoading } = useAxios({
50
- method: "get",
51
- url: "",
52
- baseURL: props.url,
53
- headers: {
54
- Accept: "application/json",
55
- },
56
- params: inputValues,
57
- });
50
+ const [isSmallScreen, setIsSmallScreen] = useState(false);
51
+ const axiosConfig = useMemo(
52
+ () => ({
53
+ method: "get",
54
+ url: "",
55
+ baseURL: props.url,
56
+ headers: {
57
+ Accept: "application/json",
58
+ },
59
+ params: fixedParams,
60
+ }),
61
+ [props.url]
62
+ );
58
63
 
59
- useEffect(() => {
60
- if (response !== null) {
61
- const optionsTopics =
62
- response.topics &&
63
- response.topics.map((d) => ({
64
- value: d.token,
65
- label: d.title,
66
- }));
64
+ const { response, error, isLoading } = useAxios(axiosConfig);
67
65
 
68
- // const taxodonnee = formatData(response.taxonomy_contact_category);
69
- const optionsTaxonomy =
70
- response.taxonomy_contact_category &&
71
- response.taxonomy_contact_category.map((d) => ({
72
- value: d.token,
73
- label: d.title,
74
- }));
75
- const optionsFacilities =
76
- response.facilities &&
77
- response.facilities.map((d) => ({
78
- value: d.token,
79
- label: d.title,
80
- }));
81
- setTopicsFilter(optionsTopics);
82
- // setTaxonomyData(taxodonnee);
83
- setTaxonomyFilter(optionsTaxonomy);
84
- setFacilitiesFilter(optionsFacilities);
85
- }
66
+ // Memoize the processed data
67
+ const processedData = useMemo(() => {
68
+ if (!response) return null;
69
+
70
+ const optionsTopics = response.topics?.map((d) => ({
71
+ value: d.token,
72
+ label: d.title,
73
+ }));
74
+
75
+ const taxodonnee = formatData(response.taxonomy_contact_category);
76
+
77
+ const optionsTaxonomy = response.taxonomy_contact_category?.map((d) => ({
78
+ value: d.token,
79
+ label: d.title,
80
+ }));
81
+
82
+ const optionsFacilities = response.facilities?.map((d) => ({
83
+ value: d.token,
84
+ label: d.title,
85
+ }));
86
+
87
+ return {
88
+ topics: optionsTopics,
89
+ taxonomy: optionsTaxonomy,
90
+ facilities: optionsFacilities,
91
+ taxodonnee,
92
+ };
86
93
  }, [response]);
87
94
 
95
+ // Update state when processed data changes
96
+ useEffect(() => {
97
+ if (processedData) {
98
+ setTopicsFilter(processedData.topics);
99
+ setTaxonomyData(processedData.taxodonnee);
100
+ setTaxonomyFilter(processedData.taxonomy);
101
+ setFacilitiesFilter(processedData.facilities);
102
+ }
103
+ }, [processedData]);
104
+
88
105
  // set values from search input
89
106
  const onChangeHandler = useCallback(({ target: { name, value } }) => {
90
107
  if (value.length > 2) {
@@ -100,6 +117,7 @@ function Filters(props) {
100
117
 
101
118
  // set values from select
102
119
  const onChangeHandlerSelect = useCallback((value, action) => {
120
+ console.log(value);
103
121
  const inputName = action.name;
104
122
  if (value) {
105
123
  setInputValues((state) => ({ ...state, [inputName]: value.value }), []);
@@ -150,6 +168,18 @@ function Filters(props) {
150
168
  setActiveComponent(index);
151
169
  };
152
170
 
171
+ // Check screen size on mount and resize
172
+ useEffect(() => {
173
+ const checkScreenSize = () => {
174
+ setIsSmallScreen(window.innerWidth <= 630);
175
+ };
176
+
177
+ checkScreenSize();
178
+ window.addEventListener("resize", checkScreenSize);
179
+
180
+ return () => window.removeEventListener("resize", checkScreenSize);
181
+ }, []);
182
+
153
183
  return (
154
184
  <React.Fragment>
155
185
  <div className="react-filters-menu">
@@ -186,29 +216,7 @@ function Filters(props) {
186
216
  </svg>
187
217
  </div>
188
218
  </form>
189
- {/* More filter*/}
190
- <button
191
- className="more-filter-btn collapsed"
192
- type="button"
193
- data-bs-toggle="collapse"
194
- data-bs-target="#collapseOne"
195
- aria-expanded="false"
196
- aria-controls="collapseOne"
197
- >
198
- <svg
199
- xmlns="http://www.w3.org/2000/svg"
200
- viewBox="0 0 32 32"
201
- style={{ height: 16, width: 16 }}
202
- fill="none"
203
- stroke="currentColor"
204
- strokeWidth="3"
205
- aria-hidden="true"
206
- display="block"
207
- overflow="visible"
208
- >
209
- <path d="M7 16H3m26 0H15M29 6h-4m-8 0H3m26 20h-4M7 16a4 4 0 108 0 4 4 0 00-8 0zM17 6a4 4 0 108 0 4 4 0 00-8 0zm0 20a4 4 0 108 0 4 4 0 00-8 0zm0 0H3"></path>
210
- </svg>
211
- </button>
219
+
212
220
  <div className="react-sep-menu"></div>
213
221
  {/* Filtre Thématique */}
214
222
  <div className="r-filter top-filter topics-Filter">
@@ -274,14 +282,54 @@ function Filters(props) {
274
282
  {/* More filter */}
275
283
 
276
284
  {/* Affichage dynamique des liens avec divs associées */}
285
+ {/* More filter*/}
286
+ <button
287
+ className="more-filter-btn more-filter-btn-annuaire collapsed"
288
+ type="button"
289
+ data-bs-toggle="collapse"
290
+ data-bs-target="#collapseOne"
291
+ aria-expanded="false"
292
+ aria-controls="collapseOne"
293
+ >
294
+ <span>
295
+ <Translator>
296
+ {({ translate }) => (
297
+ <span>
298
+ {translate({
299
+ text: "Catégories",
300
+ })}
301
+ </span>
302
+ )}
303
+ </Translator>
304
+ </span>
305
+ <svg
306
+ xmlns="http://www.w3.org/2000/svg"
307
+ viewBox="0 0 32 32"
308
+ style={{ height: 16, width: 16 }}
309
+ fill="none"
310
+ stroke="currentColor"
311
+ strokeWidth="3"
312
+ aria-hidden="true"
313
+ display="block"
314
+ overflow="visible"
315
+ >
316
+ <path d="M7 16H3m26 0H15M29 6h-4m-8 0H3m26 20h-4M7 16a4 4 0 108 0 4 4 0 00-8 0zM17 6a4 4 0 108 0 4 4 0 00-8 0zm0 20a4 4 0 108 0 4 4 0 00-8 0zm0 0H3"></path>
317
+ </svg>
318
+ </button>
277
319
  <div
278
320
  id="collapseOne"
279
- className="accordion-collapse collapse more-filter-container "
321
+ className={`accordion-collapse ${isSmallScreen ? "collapse" : ""} more-filter-container`}
280
322
  aria-labelledby="headingOne"
281
323
  data-bs-parent="#accordionExample"
282
324
  >
283
- <div className="accordion-body">
284
- {/* <div className="taxonomy-Filter">
325
+ <div className="accordion-body-annuaire">
326
+ <span className="accordion-body-annuaire-title-full-screen">
327
+ <Translator>
328
+ {({ translate }) => <span>{translate({ text: "Catégories" })}</span>}
329
+ </Translator>
330
+ </span>
331
+
332
+ <div className="taxonomy-Filter">
285
333
  {taxonomyData &&
286
334
  taxonomyData.map((donnees, i) => (
287
335
  <TaxonomyFilter
@@ -294,10 +342,10 @@ function Filters(props) {
294
342
  test={i}
295
343
  />
296
344
  ))}
297
- </div> */}
298
- <div className="r-filter facilities-Filter">
299
- {/* <label>Catégories</label> */}
300
- <Translator>
345
+ </div>
346
+ {/* <div className="r-filter facilities-Filter"> */}
347
+ {/* <label>Catégories</label> */}
348
+ {/* <Translator>
301
349
  {({ translate }) => (
302
350
  <Select
303
351
  styles={moreFilterStyles}
@@ -312,8 +360,8 @@ function Filters(props) {
312
360
  value={actTaxo && actTaxo[0]}
313
361
  />
314
362
  )}
315
- </Translator>
316
- </div>
363
+ </Translator> */}
364
+ {/* </div> */}
317
365
  </div>
318
366
  </div>
319
367
  </React.Fragment>
@@ -41,7 +41,6 @@
41
41
  .react-filters-menu {
42
42
  display: flex;
43
43
  width: 100%;
44
- margin-bottom: 1rem;
45
44
 
46
45
  .react-filters-container {
47
46
  display: flex;
@@ -178,12 +177,9 @@
178
177
  top: inherit;
179
178
  }
180
179
 
181
- &.collapsed {
180
+ &.collapsed svg {
182
181
  transform: rotate(180deg);
183
-
184
- svg {
185
- stroke: #9f9f9f;
186
- }
182
+ stroke: #9f9f9f;
187
183
  }
188
184
  }
189
185
 
@@ -197,9 +193,9 @@
197
193
  gap: 20px;
198
194
  align-items: center;
199
195
  padding: 1rem;
200
- background-color: #f8f8f8;
196
+ // background-color: #f8f8f8;
201
197
  justify-content: center;
202
- border: solid 1px #e4e4e4;
198
+ // border-bottom: solid 1px #e4e4e4;
203
199
  border-left: none;
204
200
  border-right: none;
205
201
 
@@ -1,94 +1,147 @@
1
- import React, { useState, useEffect } from "react";
1
+ import React, { useState, useEffect, useMemo, useCallback } from "react";
2
+ import PropTypes from "prop-types";
2
3
  import Select from "react-select";
3
4
  import "./TaxonomyFilter.scss";
4
5
 
5
6
  function TaxonomyFilter({ onChange, sub, title, token, isActive, setCat, onClick }) {
6
- const [select1Value, setSelect1Value] = useState(null);
7
- const [select2Value, setSelect2Value] = useState(null);
8
- const [select3Value, setSelect3Value] = useState(null);
9
- const [firstLevelOptions, setFirstLevelOptions] = useState(null);
10
- const [secondLevelOptions, setSecondLevelOptions] = useState(null);
11
- // État pour suivre l'affichage de la div associée
12
- const [secondLevelVisible, setsecondLevelVisible] = useState(false);
13
- const [thirdLevelVisible, setThirdLevelVisible] = useState(false);
14
- // const avev la valeur des filtres
15
- const [filterValue, setFilterValue] = useState({
16
- taxonomy_contact_category_for_filtering: null,
7
+ // Regroupement des états liés
8
+ const [selectValues, setSelectValues] = useState({
9
+ first: null,
10
+ second: null,
11
+ third: null,
17
12
  });
18
13
 
19
- // Object { b_start: "0", fullobjects: "1", taxonomy_contact_category_for_filtering: "ol8av3v8bn" }
14
+ const [visibility, setVisibility] = useState({
15
+ secondLevel: false,
16
+ thirdLevel: false,
17
+ });
18
+
19
+ const [options, setOptions] = useState({
20
+ firstLevel: null,
21
+ secondLevel: null,
22
+ });
23
+
24
+ // Mémoisation des options du premier niveau
25
+ const firstLevelOptions = useMemo(() => {
26
+ if (!sub) return null;
27
+ return sub.map((d) => ({
28
+ value: d.token,
29
+ label: d.title,
30
+ ...(d.sub && { sub: d.sub }),
31
+ }));
32
+ }, [sub]);
33
+
34
+ // Gestionnaires d'événements avec useCallback
35
+ const handleLinkClick = useCallback(() => {
36
+ setVisibility((prev) => ({
37
+ secondLevel: !prev.secondLevel,
38
+ thirdLevel: false,
39
+ }));
40
+ setSelectValues((prev) => ({
41
+ ...prev,
42
+ second: null,
43
+ third: null,
44
+ }));
45
+ }, []);
46
+
47
+ const onChangeSub1 = useCallback(
48
+ (value, action) => {
49
+ // console.log(value);
50
+ if (value?.sub) {
51
+ const secondLevelOptions = value.sub.map((d) => ({
52
+ value: d.token,
53
+ label: d.title,
54
+ }));
55
+ setSelectValues((prev) => ({
56
+ ...prev,
57
+ second: value.label,
58
+ third: null,
59
+ }));
60
+ setOptions((prev) => ({
61
+ ...prev,
62
+ secondLevel: secondLevelOptions,
63
+ }));
64
+ setVisibility((prev) => ({
65
+ ...prev,
66
+ thirdLevel: true,
67
+ }));
68
+ onChange(value, action);
69
+ } else {
70
+ setSelectValues((prev) => ({
71
+ ...prev,
72
+ second: value.label,
73
+ third: null,
74
+ }));
75
+ setOptions((prev) => ({
76
+ ...prev,
77
+ secondLevel: null,
78
+ }));
79
+ onChange(value, action);
80
+ }
81
+ },
82
+ [onChange]
83
+ );
84
+
85
+ const onChangeSub2 = useCallback(
86
+ (value, action) => {
87
+ setSelectValues((prev) => ({
88
+ ...prev,
89
+ third: value.label,
90
+ }));
91
+ onChange(value, action);
92
+ },
93
+ [onChange]
94
+ );
95
+
96
+ const handleApply = useCallback(
97
+ (value, title) => {
98
+ setCat((prev) => !prev);
99
+ if (!visibility.secondLevel) {
100
+ onChange(
101
+ { value, label: title },
102
+ { name: "taxonomy_contact_category_for_filtering" }
103
+ );
104
+ } else {
105
+ onChange(null, { name: "taxonomy_contact_category_for_filtering" });
106
+ }
107
+ },
108
+ [visibility.secondLevel, onChange, setCat]
109
+ );
20
110
 
21
- // Dans le composant TaxonomyFilter
111
+ // Effet pour réinitialiser l'état quand isActive change
22
112
  useEffect(() => {
23
113
  if (!isActive) {
24
- setsecondLevelVisible(false);
25
- setThirdLevelVisible(false);
26
- setSelect2Value(null);
114
+ setVisibility({
115
+ secondLevel: false,
116
+ thirdLevel: false,
117
+ });
118
+ setSelectValues((prev) => ({
119
+ ...prev,
120
+ second: null,
121
+ third: null,
122
+ }));
27
123
  }
28
124
  }, [isActive]);
29
125
 
126
+ // Effet pour mettre à jour les options du premier niveau
30
127
  useEffect(() => {
31
128
  if (sub) {
32
- const optionsSub1 = sub.map((d) => ({
33
- value: d.token,
34
- label: d.title,
35
- ...(d.sub && { sub: d.sub }),
129
+ setOptions((prev) => ({
130
+ ...prev,
131
+ firstLevel: firstLevelOptions,
36
132
  }));
37
- setFirstLevelOptions(optionsSub1);
38
133
  }
39
- }, [sub]);
40
- // Gestionnaire d'événements pour le clic sur le lien
41
- const handleLinkClick = () => {
42
- // Inverser la valeur de l'état pour afficher ou masquer la div
43
- setsecondLevelVisible(!secondLevelVisible);
44
- setSelect2Value(null);
45
- setThirdLevelVisible(false);
46
- };
47
-
48
- // Gestionnaire d'événements pour le changement de valeur dans le premier select
49
- const onChangeSub1 = (value, action) => {
50
- if (value && value.sub) {
51
- const optionsSub2 = value.sub.map((d) => ({
52
- value: d.token,
53
- label: d.title,
54
- }));
55
- setSelect2Value(value.label);
56
- setSelect3Value(null);
57
- setSecondLevelOptions(optionsSub2);
58
- setThirdLevelVisible(true);
59
- onChange(value, action);
60
- } else {
61
- setSecondLevelOptions(null);
62
- }
63
- };
64
-
65
- // Gestionnaire d'événements pour le changement de valeur dans le deuxième select
66
- const onChangeSub2 = (value, action) => {
67
- setSelect3Value(value.label);
68
- onChange(value, action);
69
- };
70
-
71
- // send the value to the first level (a link)
72
- const handleApply = (value, title) => {
73
- setCat((prevCat) => !prevCat);
74
- if (!secondLevelVisible) {
75
- onChange(
76
- { value: value, label: title },
77
- { name: "taxonomy_contact_category_for_filtering" }
78
- );
79
- } else {
80
- onChange(null, { name: "taxonomy_contact_category_for_filtering" });
81
- }
82
- };
134
+ }, [sub, firstLevelOptions]);
83
135
 
84
136
  return (
85
137
  <div onClick={onClick}>
86
138
  <div
87
139
  className={
88
- secondLevelVisible ? "dropDownFilter dropDownFilter-active" : "dropDownFilter"
140
+ visibility.secondLevel
141
+ ? "dropDownFilter dropDownFilter-active"
142
+ : "dropDownFilter"
89
143
  }
90
144
  >
91
- {/* Lien avec gestionnaire d'événements */}
92
145
  <a
93
146
  className="sub0"
94
147
  href="#"
@@ -96,48 +149,56 @@ function TaxonomyFilter({ onChange, sub, title, token, isActive, setCat, onClick
96
149
  onClick={(e) => {
97
150
  e.preventDefault();
98
151
  handleLinkClick();
99
- handleApply(token, title); // Pass the correct value to handleApply
152
+ handleApply(token, title);
100
153
  }}
101
154
  >
102
155
  {title}
103
156
  </a>
104
157
 
105
- {/* Div conditionnellement rendue en fonction de l'état */}
106
- {firstLevelOptions && (
158
+ {options.firstLevel && (
107
159
  <div
108
160
  className={
109
- secondLevelVisible
161
+ visibility.secondLevel
110
162
  ? "sub1 dropDownFilter-visible"
111
163
  : "sub1 dropDownFilter-invisble"
112
164
  }
113
165
  >
114
166
  <Select
115
- name={"taxonomy_contact_category_for_filtering"}
116
- className="select-custom-class library-facilities"
167
+ name="taxonomy_contact_category_for_filtering"
168
+ className={`select-custom-class library-facilities react-select-container ${
169
+ selectValues.second && selectValues.second !== "Catégories"
170
+ ? "select-has-value"
171
+ : ""
172
+ }`}
173
+ classNamePrefix="react-select-custom-multi"
117
174
  onChange={onChangeSub1}
118
- options={firstLevelOptions}
119
- value={select2Value}
120
- placeholder={select2Value ? select2Value : "Catégories"}
175
+ options={options.firstLevel}
176
+ value={selectValues.second}
177
+ placeholder={selectValues.second ? selectValues.second : "Catégories"}
121
178
  />
122
179
  </div>
123
180
  )}
124
181
 
125
- {/* Div 3 conditionnellement rendue en fonction de l'état */}
126
- {secondLevelOptions && (
182
+ {options.secondLevel && (
127
183
  <div
128
184
  className={
129
- thirdLevelVisible
185
+ visibility.thirdLevel
130
186
  ? "sub2 dropDownFilter-visible"
131
187
  : "sub2 dropDownFilter-invisble"
132
188
  }
133
189
  >
134
190
  <Select
135
- name={"taxonomy_contact_category_for_filtering"}
136
- className="select-custom-class library-facilities"
191
+ name="taxonomy_contact_category_for_filtering"
192
+ className={`react-custom-multi-select-container library-facilities ${
193
+ selectValues.third && selectValues.third !== "Catégories"
194
+ ? "select-has-value"
195
+ : ""
196
+ }`}
197
+ classNamePrefix="react-select-custom-multi"
137
198
  onChange={onChangeSub2}
138
- options={secondLevelOptions}
139
- value={select3Value}
140
- placeholder={select3Value ? select3Value : "Catégories"}
199
+ options={options.secondLevel}
200
+ value={selectValues.third}
201
+ placeholder={selectValues.third ? selectValues.third : "Catégories"}
141
202
  />
142
203
  </div>
143
204
  )}
@@ -146,4 +207,25 @@ function TaxonomyFilter({ onChange, sub, title, token, isActive, setCat, onClick
146
207
  );
147
208
  }
148
209
 
210
+ TaxonomyFilter.propTypes = {
211
+ onChange: PropTypes.func.isRequired,
212
+ sub: PropTypes.arrayOf(
213
+ PropTypes.shape({
214
+ token: PropTypes.string.isRequired,
215
+ title: PropTypes.string.isRequired,
216
+ sub: PropTypes.array,
217
+ })
218
+ ),
219
+ title: PropTypes.string.isRequired,
220
+ token: PropTypes.string.isRequired,
221
+ isActive: PropTypes.bool,
222
+ setCat: PropTypes.func.isRequired,
223
+ onClick: PropTypes.func,
224
+ };
225
+
226
+ TaxonomyFilter.defaultProps = {
227
+ isActive: false,
228
+ onClick: () => {},
229
+ };
230
+
149
231
  export default TaxonomyFilter;