imio.smartweb.core 1.2.90__py3-none-any.whl → 1.3__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 (96) hide show
  1. imio/smartweb/core/browser/controlpanel.py +42 -5
  2. imio/smartweb/core/browser/utils.py +4 -1
  3. imio/smartweb/core/configure.zcml +5 -1
  4. imio/smartweb/core/contents/__init__.py +2 -0
  5. imio/smartweb/core/contents/rest/campaign/__init__.py +0 -0
  6. imio/smartweb/core/contents/rest/campaign/configure.zcml +80 -0
  7. imio/smartweb/core/contents/rest/campaign/content.py +83 -0
  8. imio/smartweb/core/contents/rest/campaign/endpoint.py +211 -0
  9. imio/smartweb/core/contents/rest/campaign/view.pt +19 -0
  10. imio/smartweb/core/contents/rest/campaign/view.py +29 -0
  11. imio/smartweb/core/contents/rest/configure.zcml +1 -0
  12. imio/smartweb/core/interfaces.py +4 -0
  13. imio/smartweb/core/overrides.zcml +10 -0
  14. imio/smartweb/core/profiles/default/metadata.xml +1 -1
  15. imio/smartweb/core/profiles/ideabox/browserlayer.xml +7 -0
  16. imio/smartweb/core/profiles/ideabox/metadata.xml +5 -0
  17. imio/smartweb/core/profiles/ideabox/registry/iaideabox.xml +9 -0
  18. imio/smartweb/core/profiles/ideabox/types/imio.smartweb.CampaignView.xml +40 -0
  19. imio/smartweb/core/profiles/ideabox/types/imio.smartweb.Folder.xml +71 -0
  20. imio/smartweb/core/profiles/ideabox/types.xml +17 -0
  21. imio/smartweb/core/profiles/ideabox_uninstall/browserlayer.xml +7 -0
  22. imio/smartweb/core/profiles/ideabox_uninstall/types/imio.smartweb.Folder.xml +25 -0
  23. imio/smartweb/core/profiles/ideabox_uninstall/types.xml +4 -0
  24. imio/smartweb/core/profiles/testing/metadata.xml +1 -0
  25. imio/smartweb/core/profiles/testing/registry.xml +2 -2
  26. imio/smartweb/core/profiles.zcml +18 -0
  27. imio/smartweb/core/subscribers.py +27 -1
  28. imio/smartweb/core/subscribers.zcml +8 -0
  29. imio/smartweb/core/tests/resources/json_ideabox_campaign.json +222 -0
  30. imio/smartweb/core/tests/resources/json_ideabox_campaigns.json +425 -0
  31. imio/smartweb/core/tests/resources/json_ideabox_projects.json +1871 -0
  32. imio/smartweb/core/tests/test_iadeliberations.py +38 -40
  33. imio/smartweb/core/tests/test_ideabox.py +120 -0
  34. imio/smartweb/core/tests/test_procedure.py +7 -3
  35. imio/smartweb/core/tests/test_rest.py +7 -0
  36. imio/smartweb/core/tests/test_vocabularies.py +8 -10
  37. imio/smartweb/core/upgrades/configure.zcml +16 -1
  38. imio/smartweb/core/upgrades/upgrades.py +64 -0
  39. imio/smartweb/core/utils.py +33 -0
  40. imio/smartweb/core/viewlets/actions.py +10 -0
  41. imio/smartweb/core/viewlets/header_actions.pt +2 -0
  42. imio/smartweb/core/viewlets/offcanvas.pt +31 -6
  43. imio/smartweb/core/viewlets/ogptags.py +9 -0
  44. imio/smartweb/core/viewlets/subsite_logo.pt +1 -1
  45. imio/smartweb/core/vocabularies.py +35 -4
  46. imio/smartweb/core/vocabularies.zcml +6 -0
  47. imio/smartweb/core/webcomponents/build/css/373.smartweb-webcomponents-compiled.css +1 -1
  48. imio/smartweb/core/webcomponents/build/css/420.smartweb-webcomponents-compiled.css +1 -0
  49. imio/smartweb/core/webcomponents/build/css/486.smartweb-webcomponents-compiled.css +1 -1
  50. imio/smartweb/core/webcomponents/build/css/666.smartweb-webcomponents-compiled.css +1 -0
  51. imio/smartweb/core/webcomponents/build/css/884.smartweb-webcomponents-compiled.css +1 -1
  52. imio/smartweb/core/webcomponents/build/css/smartweb-webcomponents-compiled.css +1 -1
  53. imio/smartweb/core/webcomponents/build/js/141.smartweb-webcomponents-compiled.js +2 -0
  54. imio/smartweb/core/webcomponents/build/js/{828.smartweb-webcomponents-compiled.js.LICENSE.txt → 141.smartweb-webcomponents-compiled.js.LICENSE.txt} +3 -3
  55. imio/smartweb/core/webcomponents/build/js/15.smartweb-webcomponents-compiled.js +2 -0
  56. imio/smartweb/core/webcomponents/build/js/21.smartweb-webcomponents-compiled.js +1 -0
  57. imio/smartweb/core/webcomponents/build/js/218.smartweb-webcomponents-compiled.js +1 -1
  58. imio/smartweb/core/webcomponents/build/js/218.smartweb-webcomponents-compiled.js.LICENSE.txt +0 -5
  59. imio/smartweb/core/webcomponents/build/js/373.smartweb-webcomponents-compiled.js +1 -1
  60. imio/smartweb/core/webcomponents/build/js/486.smartweb-webcomponents-compiled.js +1 -1
  61. imio/smartweb/core/webcomponents/build/js/666.smartweb-webcomponents-compiled.js +1 -0
  62. imio/smartweb/core/webcomponents/build/js/799.smartweb-webcomponents-compiled.js +1 -1
  63. imio/smartweb/core/webcomponents/build/js/824.smartweb-webcomponents-compiled.js +1 -1
  64. imio/smartweb/core/webcomponents/build/js/884.smartweb-webcomponents-compiled.js +1 -1
  65. imio/smartweb/core/webcomponents/build/js/919.smartweb-webcomponents-compiled.js +1 -1
  66. imio/smartweb/core/webcomponents/build/js/922.smartweb-webcomponents-compiled.js +1 -0
  67. imio/smartweb/core/webcomponents/build/js/smartweb-webcomponents-compiled.js +1 -1
  68. imio/smartweb/core/webcomponents/package.json +80 -80
  69. imio/smartweb/core/webcomponents/src/components/Annuaire/Annuaire.scss +1 -0
  70. imio/smartweb/core/webcomponents/src/components/Campaign/Campaign.jsx +306 -0
  71. imio/smartweb/core/webcomponents/src/components/Campaign/Campaign.scss +672 -0
  72. imio/smartweb/core/webcomponents/src/components/Campaign/CampaignCard/CampaignCard.jsx +79 -0
  73. imio/smartweb/core/webcomponents/src/components/Campaign/CampaignContent/CampaignContent.jsx +193 -0
  74. imio/smartweb/core/webcomponents/src/components/Campaign/CampaignList/CampaignList.jsx +67 -0
  75. imio/smartweb/core/webcomponents/src/components/Campaign/Filters/Filter.jsx +259 -0
  76. imio/smartweb/core/webcomponents/src/components/Campaign/index.js +2 -0
  77. imio/smartweb/core/webcomponents/src/components/Filters/MainFilter.scss +1 -0
  78. imio/smartweb/core/webcomponents/src/components/News/NewsContent/NewsContent.jsx +0 -1
  79. imio/smartweb/core/webcomponents/src/hooks/useAxios.js +45 -9
  80. imio/smartweb/core/webcomponents/src/index.jsx +2 -0
  81. imio/smartweb/core/webcomponents/src/index.scss +2 -2
  82. imio/smartweb/core/webcomponents/src/utils/CampaignMap.jsx +177 -0
  83. imio/smartweb/core/webcomponents/src/utils/Map.jsx +1 -1
  84. imio/smartweb/core/webcomponents/src/utils/Map.scss +15 -1
  85. imio/smartweb/core/webcomponents/src/utils/translation.js +235 -199
  86. {imio.smartweb.core-1.2.90.dist-info → imio.smartweb.core-1.3.dist-info}/METADATA +18 -1
  87. {imio.smartweb.core-1.2.90.dist-info → imio.smartweb.core-1.3.dist-info}/RECORD +94 -61
  88. imio/smartweb/core/webcomponents/build/js/499.smartweb-webcomponents-compiled.js +0 -2
  89. imio/smartweb/core/webcomponents/build/js/828.smartweb-webcomponents-compiled.js +0 -2
  90. /imio/smartweb/core/webcomponents/build/js/{499.smartweb-webcomponents-compiled.js.LICENSE.txt → 15.smartweb-webcomponents-compiled.js.LICENSE.txt} +0 -0
  91. /imio.smartweb.core-1.2.90-py3.12-nspkg.pth → /imio.smartweb.core-1.3-py3.12-nspkg.pth +0 -0
  92. {imio.smartweb.core-1.2.90.dist-info → imio.smartweb.core-1.3.dist-info}/LICENSE.GPL +0 -0
  93. {imio.smartweb.core-1.2.90.dist-info → imio.smartweb.core-1.3.dist-info}/LICENSE.rst +0 -0
  94. {imio.smartweb.core-1.2.90.dist-info → imio.smartweb.core-1.3.dist-info}/WHEEL +0 -0
  95. {imio.smartweb.core-1.2.90.dist-info → imio.smartweb.core-1.3.dist-info}/namespace_packages.txt +0 -0
  96. {imio.smartweb.core-1.2.90.dist-info → imio.smartweb.core-1.3.dist-info}/top_level.txt +0 -0
@@ -1,82 +1,82 @@
1
1
  {
2
- "name": "imio.smartweb.core-webcomponents",
3
- "version": "0.0.1",
4
- "description": "Various React components exported as web components to use directly in template (.pt) files",
5
- "private": true,
6
- "scripts": {
7
- "build": "webpack --mode=production --progress --stats",
8
- "build-dev": "webpack --mode=development --progress",
9
- "watch": "webpack serve --mode=development --progress",
10
- "prettier": "prettier --check 'src/**/*.{js,jsx,ts,tsx,json}'",
11
- "prettier:fix": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json}'",
12
- "lint": "eslint --max-warnings=0 'src/**/*.{js,jsx,json}'",
13
- "lint:fix": "eslint --fix 'src/**/*.{js,jsx,json}'"
14
- },
15
- "author": "iMio",
16
- "license": "GPLv2",
17
- "browserslist": [
18
- "> 0.10%",
19
- "not dead"
20
- ],
21
- "devDependencies": {
22
- "@babel/core": "^7.24.3",
23
- "@babel/plugin-proposal-async-generator-functions": "^7.20.7",
24
- "@babel/plugin-transform-react-jsx": "^7.23.4",
25
- "@babel/preset-env": "^7.24.3",
26
- "@fullhuman/postcss-purgecss": "^5.0.0",
27
- "@svgr/webpack": "^8.1.0",
28
- "ajv": "^7.2.4",
29
- "autoprefixer": "^10.4.19",
30
- "babel-loader": "^9.1.3",
31
- "clean-webpack-plugin": "^4.0.0",
32
- "core-js": "^3.36.1",
33
- "css-loader": "^6.10.0",
34
- "css-minimizer-webpack-plugin": "^6.0.0",
35
- "eslint": "^8.57.0",
36
- "eslint-plugin-import": "^2.29.1",
37
- "eslint-plugin-react": "^7.34.1",
38
- "file-loader": "^6.2.0",
39
- "json-minimizer-webpack-plugin": "^5.0.0",
40
- "mini-css-extract-plugin": "^2.8.1",
41
- "postcss": "^8.4.38",
42
- "postcss-loader": "^8.1.1",
43
- "prettier": "3.2.5",
44
- "purgecss": "^5.0.0",
45
- "sass": "^1.72.0",
46
- "sass-loader": "^14.1.1",
47
- "style-loader": "^3.3.4",
48
- "webpack": "^5.91.0",
49
- "webpack-cli": "^5.1.4",
50
- "webpack-dev-server": "^5.0.4",
51
- "xml2js": "^0.6.2"
52
- },
53
- "dependencies": {
54
- "@babel/polyfill": "^7.12.1",
55
- "@loadable/component": "^5.16.3",
56
- "axios": "^1.6.8",
57
- "babel-polyfill": "^6.26.0",
58
- "bootstrap-icons": "^1.11.3",
59
- "date-fns": "^3.6.0",
60
- "flexbin": "^0.2.0",
61
- "leaflet": "^1.9.4",
62
- "lodash": "^4.17.21",
63
- "moment": "^2.30.1",
64
- "query-string": "^9.0.0",
65
- "react": "^18.2.0",
66
- "react-bootstrap": "^2.10.2",
67
- "react-content-loader": "^7.0.0",
68
- "react-datepicker": "^6.6.0",
69
- "react-dom": "^18.2.0",
70
- "react-highlight-words": "^0.20.0",
71
- "react-leaflet": "^4.2.1",
72
- "react-markdown": "^9.0.1",
73
- "react-moment": "^1.1.3",
74
- "react-router-dom": "^6.22.3",
75
- "react-select": "^5.8.0",
76
- "react-translated": "^2.5.0",
77
- "react-web-component": "^2.0.2",
78
- "react-web-component-style-loader": "^0.1.4-alpha",
79
- "remove-accents": "^0.5.0",
80
- "spotlight.js": "^0.7.8"
81
- }
2
+ "name": "imio.smartweb.core-webcomponents",
3
+ "version": "0.0.1",
4
+ "description": "Various React components exported as web components to use directly in template (.pt) files",
5
+ "private": true,
6
+ "scripts": {
7
+ "build": "webpack --mode=production --progress --stats",
8
+ "build-dev": "webpack --mode=development --progress",
9
+ "watch": "webpack serve --mode=development --progress",
10
+ "prettier": "prettier --check 'src/**/*.{js,jsx,ts,tsx,json}'",
11
+ "prettier:fix": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json}'",
12
+ "lint": "eslint --max-warnings=0 'src/**/*.{js,jsx,json}'",
13
+ "lint:fix": "eslint --fix 'src/**/*.{js,jsx,json}'"
14
+ },
15
+ "author": "iMio",
16
+ "license": "GPLv2",
17
+ "browserslist": [
18
+ "> 0.10%",
19
+ "not dead"
20
+ ],
21
+ "devDependencies": {
22
+ "@babel/core": "^7.24.3",
23
+ "@babel/plugin-proposal-async-generator-functions": "^7.20.7",
24
+ "@babel/plugin-transform-react-jsx": "^7.23.4",
25
+ "@babel/preset-env": "^7.24.3",
26
+ "@fullhuman/postcss-purgecss": "^5.0.0",
27
+ "@svgr/webpack": "^8.1.0",
28
+ "ajv": "^7.2.4",
29
+ "autoprefixer": "^10.4.19",
30
+ "babel-loader": "^9.1.3",
31
+ "clean-webpack-plugin": "^4.0.0",
32
+ "core-js": "^3.36.1",
33
+ "css-loader": "^6.10.0",
34
+ "css-minimizer-webpack-plugin": "^6.0.0",
35
+ "eslint": "^8.57.0",
36
+ "eslint-plugin-import": "^2.29.1",
37
+ "eslint-plugin-react": "^7.34.1",
38
+ "file-loader": "^6.2.0",
39
+ "json-minimizer-webpack-plugin": "^5.0.0",
40
+ "mini-css-extract-plugin": "^2.8.1",
41
+ "postcss": "^8.4.38",
42
+ "postcss-loader": "^8.1.1",
43
+ "prettier": "3.2.5",
44
+ "purgecss": "^5.0.0",
45
+ "sass": "^1.83.4",
46
+ "sass-loader": "^16.0.4",
47
+ "style-loader": "^3.3.4",
48
+ "webpack": "^5.91.0",
49
+ "webpack-cli": "^5.1.4",
50
+ "webpack-dev-server": "^5.0.4",
51
+ "xml2js": "^0.6.2"
52
+ },
53
+ "dependencies": {
54
+ "@babel/polyfill": "^7.12.1",
55
+ "@loadable/component": "^5.16.3",
56
+ "axios": "^1.6.8",
57
+ "babel-polyfill": "^6.26.0",
58
+ "bootstrap-icons": "^1.11.3",
59
+ "date-fns": "^3.6.0",
60
+ "flexbin": "^0.2.0",
61
+ "leaflet": "^1.9.4",
62
+ "lodash": "^4.17.21",
63
+ "moment": "^2.30.1",
64
+ "query-string": "^9.0.0",
65
+ "react": "^18.2.0",
66
+ "react-bootstrap": "^2.10.2",
67
+ "react-content-loader": "^7.0.0",
68
+ "react-datepicker": "^6.6.0",
69
+ "react-dom": "^18.2.0",
70
+ "react-highlight-words": "^0.20.0",
71
+ "react-leaflet": "^4.2.1",
72
+ "react-markdown": "^9.0.1",
73
+ "react-moment": "^1.1.3",
74
+ "react-router-dom": "^6.22.3",
75
+ "react-select": "^5.8.0",
76
+ "react-translated": "^2.5.0",
77
+ "react-web-component": "^2.0.2",
78
+ "react-web-component-style-loader": "^0.1.4-alpha",
79
+ "remove-accents": "^0.5.0",
80
+ "spotlight.js": "^0.7.8"
81
+ }
82
82
  }
@@ -117,6 +117,7 @@ article > header {
117
117
  background-color: #000;
118
118
  background-size: cover;
119
119
  border-radius: 5px;
120
+
120
121
  &.r-item-img-placeholder {
121
122
  background-color: #f2f2f2;
122
123
  }
@@ -0,0 +1,306 @@
1
+ import React, { useEffect, useState, useContext, useRef } from "react";
2
+ import { BrowserRouter, Routes, Route } from "react-router-dom";
3
+ import { ScrollContext } from "../../hooks/ScrollContext";
4
+ import Filters from "./Filters/Filter";
5
+ import CampaignContent from "./CampaignContent/CampaignContent";
6
+ import CampaignList from "./CampaignList/CampaignList";
7
+ import Map from "../../utils/CampaignMap";
8
+ import useAxios from "../../hooks/useAxios";
9
+ import "./Campaign.scss";
10
+ import "../Filters/MainFilter.scss";
11
+ import useFilterQuery from "../../hooks/useFilterQuery";
12
+ import { Provider, Translate } from "react-translated";
13
+ import translation from "../../utils/translation";
14
+ import moment from "moment";
15
+ import queryString from "query-string";
16
+
17
+ export default function Campaign(props) {
18
+ // Utilisation de useState pour gérer la valeur du contexte
19
+ const [scrollPos, setScrollPos] = useState(0);
20
+ // Fonction pour mettre à jour la position du scroll
21
+ const updateScrollPos = (newScrollPos) => {
22
+ setScrollPos(newScrollPos);
23
+ };
24
+ return (
25
+ <BrowserRouter basename={props.viewPath}>
26
+ <Provider language={props.currentLanguage} translation={translation}>
27
+ <ScrollContext.Provider value={{ scrollPos, updateScrollPos }}>
28
+ <CampaignView
29
+ queryZonesUrl={props.queryZonesUrl}
30
+ queryTopicsUrl={props.queryTopicsUrl}
31
+ queryUrl={props.queryUrl}
32
+ proposeUrl={props.proposeUrl}
33
+ batchSize={props.batchSize}
34
+ displayMap={props.displayMap}
35
+ language={props.currentLanguage}
36
+ />
37
+ </ScrollContext.Provider>
38
+ </Provider>
39
+ </BrowserRouter>
40
+ );
41
+ }
42
+ function CampaignView(props) {
43
+ const { u, ...parsed } = Object.assign(
44
+ {
45
+ b_start: 0,
46
+ fullobjects: 1,
47
+ "event_dates.query": [moment().format("YYYY-MM-DD")],
48
+ "event_dates.range": props.onlyPastCampaign === "True" ? "max" : "min",
49
+ },
50
+ queryString.parse(useFilterQuery().toString())
51
+ );
52
+ const { scrollPos, updateScrollPos } = useContext(ScrollContext);
53
+ const [itemsArray, setItemsArray] = useState([]);
54
+ const [itemsNumber, setItemsNumber] = useState([]);
55
+ const [clickId, setClickId] = useState(null);
56
+ const [hoverId, setHoverId] = useState(null);
57
+ const [filters, setFilters] = useState({ b_start: 0 });
58
+ const [batchStart, setBatchStart] = useState(0);
59
+ const [loadMoreLaunch, setLoadMoreLaunch] = useState(false);
60
+ const displayMap = props.displayMap === "True" ? true : false;
61
+ const { response, error, isLoading, isMore } = useAxios(
62
+ {
63
+ method: "get",
64
+ url: "",
65
+ baseURL: props.queryUrl,
66
+ headers: {
67
+ Accept: "application/json",
68
+ },
69
+ params: filters,
70
+ paramsSerializer: { indexes: null },
71
+ load: loadMoreLaunch,
72
+ },
73
+ []
74
+ );
75
+
76
+ // set all campaigns state
77
+ useEffect(() => {
78
+ if (response !== null) {
79
+ if (isMore) {
80
+ setItemsArray((itemsArray) => [...itemsArray, ...response.items]);
81
+ } else {
82
+ setItemsArray(response.items);
83
+ }
84
+ setItemsNumber(response.items_total);
85
+ }
86
+ }, [response]);
87
+
88
+ // set state id when clicked on list element
89
+ const clickID = (id) => {
90
+ setClickId(id);
91
+ };
92
+
93
+ // set state hoverId when hover on list element
94
+ const hoverID = (id) => {
95
+ setHoverId(id);
96
+ };
97
+
98
+ // set state filters when active filter selection
99
+ const filtersChange = (value) => {
100
+ setLoadMoreLaunch(false);
101
+ setBatchStart(() => 0);
102
+ setFilters(value);
103
+ window.scrollTo(0, 0);
104
+ };
105
+
106
+ // set batch
107
+ const loadMore = () => {
108
+ updateScrollPos(window.scrollY);
109
+ setBatchStart((batchStart) => batchStart + parseInt(props.batchSize));
110
+ setLoadMoreLaunch(true);
111
+ };
112
+
113
+ // Update filters Batch
114
+ // useEffect(() => {
115
+ // setFilters((prevFilters) => {
116
+ // return {
117
+ // ...prevFilters,
118
+ // b_start: batchStart,
119
+ // };
120
+ // });
121
+ // }, [batchStart]);
122
+
123
+ // filter top style
124
+ const filterRef = useRef();
125
+ const [style, setStyle] = React.useState({ height: 0 });
126
+ const [headerHeight, setHeaderHeight] = useState(0);
127
+ useEffect(() => {
128
+ setStyle({
129
+ height: filterRef.current.clientHeight,
130
+ });
131
+ setHeaderHeight(filterRef.current.offsetTop);
132
+ }, [filterRef]);
133
+
134
+ // coditional list render
135
+ let listRender;
136
+ let MapRender;
137
+ if (itemsArray && itemsArray.length > 0) {
138
+ listRender = <CampaignList onChange={clickID} itemsArray={itemsArray} onHover={hoverID} />;
139
+ MapRender = (
140
+ <Map
141
+ headerHeight={style.height + headerHeight}
142
+ clickId={clickId}
143
+ hoverId={hoverId}
144
+ items={itemsArray}
145
+ queryUrl={props.queryUrl}
146
+ />
147
+ );
148
+ } else if (!isLoading) {
149
+ listRender = (
150
+ <p>
151
+ <Translate text="Aucun événement n'a été trouvé" />
152
+ </p>
153
+ );
154
+ }
155
+ const divLoader = (
156
+ <div className="lds-roller-container">
157
+ <div className="lds-roller">
158
+ <div></div>
159
+ <div></div>
160
+ <div></div>
161
+ <div></div>
162
+ <div></div>
163
+ <div></div>
164
+ <div></div>
165
+ <div></div>
166
+ </div>
167
+ </div>
168
+ );
169
+ return (
170
+ <div className={`ref ${displayMap ? "view-map" : "no-map"}`}>
171
+ <div
172
+ className="r-result-filter-container"
173
+ ref={filterRef}
174
+ style={{ top: headerHeight }}
175
+ >
176
+ <div
177
+ id="r-result-filter"
178
+ className="r-result-filter container annuaire-result-filter"
179
+ >
180
+ <Filters
181
+ queryZonesUrl={props.queryZonesUrl}
182
+ queryTopicsUrl={props.queryTopicsUrl}
183
+ activeFilter={filters}
184
+ onChange={filtersChange}
185
+ />
186
+ {props.proposeUrl && (
187
+ <div className="r-add-contact">
188
+ <a target="_blank" rel="noreferrer" href={props.proposeUrl}>
189
+ <Translate text="Proposer un projet" />
190
+ <svg
191
+ xmlns="http://www.w3.org/2000/svg"
192
+ width="16"
193
+ height="16"
194
+ fill="currentColor"
195
+ className="bi bi-plus-circle"
196
+ viewBox="0 0 16 16"
197
+ >
198
+ <path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16" />
199
+ <path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4" />
200
+ </svg>
201
+ </a>
202
+ </div>
203
+ )}
204
+ {itemsNumber > 0 ? (
205
+ <p className="r-results-numbers">
206
+ <span>{itemsNumber}</span>
207
+ {itemsNumber > 1 ? (
208
+ <Translate text="projets trouvés" />
209
+ ) : (
210
+ <Translate text="projet trouvé" />
211
+ )}
212
+ </p>
213
+ ) : (
214
+ <p className="r-results-numbers">
215
+ <Translate text="Aucun résultat" />
216
+ </p>
217
+ )}
218
+ </div>
219
+ </div>
220
+ <Routes>
221
+ <Route
222
+ exact
223
+ path="/"
224
+ element={
225
+ <div className="r-wrapper container r-campaign-wrapper">
226
+ <div className="r-result r-campaign-result">
227
+ {itemsNumber > 0 ? (
228
+ <p className="r-results-numbers">
229
+ <span>{itemsNumber}</span>
230
+ {itemsNumber > 1 ? (
231
+ <Translate text="projets trouvés" />
232
+ ) : (
233
+ <Translate text="projet trouvé" />
234
+ )}
235
+ </p>
236
+ ) : (
237
+ <p className="r-results-numbers">
238
+ <Translate text="Aucun résultat" />
239
+ </p>
240
+ )}
241
+ <div>{listRender}</div>
242
+ <div className="r-load-more">
243
+ {itemsNumber - props.batchSize > batchStart ? (
244
+ <div>
245
+ <span className="no-more-result">
246
+ {isLoading ? divLoader : ""}
247
+ </span>
248
+ <button onClick={loadMore} className="btn-grad">
249
+ {isLoading ? (
250
+ <Translate text="Chargement..." />
251
+ ) : (
252
+ <Translate text="Plus de résultats" />
253
+ )}
254
+ </button>
255
+ </div>
256
+ ) : (
257
+ <span className="no-more-result">
258
+ {isLoading ? divLoader : ""}
259
+ </span>
260
+ )}
261
+ </div>
262
+ </div>
263
+ {displayMap && (
264
+ <div
265
+ className="r-map campaign-map"
266
+ style={{
267
+ top: style.height + headerHeight,
268
+ height: "calc(100vh-" + style.height + headerHeight,
269
+ }}
270
+ >
271
+ {MapRender}
272
+ </div>
273
+ )}
274
+ </div>
275
+ }
276
+ ></Route>
277
+ <Route
278
+ path={"/:name"}
279
+ element={
280
+ <div className="r-wrapper container r-campaign-wrapper">
281
+ <div className="r-result r-campaign-result">
282
+ <CampaignContent
283
+ queryUrl={props.queryUrl}
284
+ onChange={clickID}
285
+ onlyPastCampaign={props.onlyPastCampaign}
286
+ contextAuthenticatedUser={props.contextAuthenticatedUser}
287
+ />
288
+ </div>
289
+ {displayMap && (
290
+ <div
291
+ className="r-map campaign-map"
292
+ style={{
293
+ top: style.height + headerHeight,
294
+ height: "calc(100vh-" + style.height + headerHeight,
295
+ }}
296
+ >
297
+ {MapRender}
298
+ </div>
299
+ )}
300
+ </div>
301
+ }
302
+ ></Route>
303
+ </Routes>
304
+ </div>
305
+ );
306
+ }