pssm legend - select

This commit is contained in:
louai98 2024-06-10 17:16:53 +02:00
parent a1037291e5
commit f2c0c1ab3c
9 changed files with 326 additions and 136 deletions

View File

@ -759,7 +759,6 @@ class ControlInAfricaMap extends React.Component {
<button onClick={this.zoomIn}>+</button>
<button onClick={this.zoomOut}>-</button>
<button onClick={this.resetMap}>*</button>
</div>
<div className="country-select">

View File

@ -3,6 +3,7 @@ import Card_ from "../../UI/Card_/Card_";
import DOMPurify from "dompurify";
import parse from "html-react-parser";
import TruncateContent from "../../Helpers/TruncateContent/TruncateContent";
import Collapse from "react-bootstrap/Collapse";
const Blurb = () => {
DOMPurify.addHook("afterSanitizeAttributes", function (node) {
@ -30,15 +31,14 @@ const Blurb = () => {
return (
<Card_ className="p-3">
<TruncateContent>
<MainText footnotes={footnotes} />
<Footnotes footnotes={footnotes} />
</TruncateContent>
</Card_>
);
};
const MainText = ({ footnotes }) => {
const [open, setOpen] = useState(false);
const [isHidden, setIsHidden] = useState(true);
return (
<div>
<h3>Physical Security and Stockpile Management (PSSM)</h3>
@ -61,85 +61,84 @@ const MainText = ({ footnotes }) => {
</sup>
.
</p>
<Collapse in={open}>
<div id="example-collapse-text">
<p>
Physical Security and Stockpile Management (PSSM) consists of the
procedures and activities that are necessary for the safe and secure
accounting, storage, transportation and handling of SALW
procedures and activities that are necessary for the safe and
secure accounting, storage, transportation and handling of SALW
<sup>
<a href="#footnote-3">3</a>
</sup>
. It can therefore be viewed as a key element of practical weapons and
ammunition management, and it significantly decreases the risk of
illicit proliferation, trafficking and diversion of firearms,
ammunition, and explosives as well as reduces the risk of Unintentional
Munitions Explosions.
. It can therefore be viewed as a key element of practical weapons
and ammunition management, and it significantly decreases the risk
of illicit proliferation, trafficking and diversion of firearms,
ammunition, and explosives as well as reduces the risk of
Unintentional Munitions Explosions.
</p>
<p>
Responsible management of stockpiles can therefore positively impact on
efforts to reduce armed violence and contribute towards enhancing the
security of the surrounding communities as well as the security at the
local, national and regional level.
Responsible management of stockpiles can therefore positively impact
on efforts to reduce armed violence and contribute towards enhancing
the security of the surrounding communities as well as the security
at the local, national and regional level.
</p>
<h3>Regional PSSM Training of Trainers (ToT) processes</h3>
<p>
Since 2016, the bicc advisory team on Weapons and Ammunition Management
(WAM) has been supporting two multi-stakeholder regional PSSM Training
of Trainers (ToT) processes; one in East Africa (with the Regional
Centre on Small Arms in the Great Lakes Region, the Horn of Africa and
Bordering States, RECSA) and one in West Africa (with the Economic
Community of West African States, ECOWAS).
Since 2016, the bicc advisory team on Weapons and Ammunition
Management (WAM) has been supporting two multi-stakeholder regional
PSSM Training of Trainers (ToT) processes; one in East Africa (with
the Regional Centre on Small Arms in the Great Lakes Region, the
Horn of Africa and Bordering States, RECSA) and one in West Africa
(with the Economic Community of West African States, ECOWAS).
</p>
<p>
The aim of both processes was to support and enhance regional ownership,
strengthen PSSM capacities, establish sustainable structures by creating
a regional trainer pool whose trainers can independently train more
trainers that equally possess the necessary regional and local
knowledge, thereby decreasing a dependency on foreign experts. The focus
on regional ownership and sustainability represents a crucial piece of
the peace and security puzzle, in alignment with SDG 16.
The aim of both processes was to support and enhance regional
ownership, strengthen PSSM capacities, establish sustainable
structures by creating a regional trainer pool whose trainers can
independently train more trainers that equally possess the necessary
regional and local knowledge, thereby decreasing a dependency on
foreign experts. The focus on regional ownership and sustainability
represents a crucial piece of the peace and security puzzle, in
alignment with SDG 16.
</p>
<p>
Based on the UN Programme of Action, and acknowledging PSSM as a key
element of WAM, the Multinational Small Arms and Ammunition Group (MSAG)
initiated a training programme on the security and stockpile management
of weapons, ammunition, and explosives for East African states in Kenya
in 2012. Participants of the ToT processes derived from among the
military, police and wildlife service sectors. Up until March 2024, 469
participants have been trained, out of which 42 were certified as PSSM
Instructors and 13 as Senior Instructors. The map below shows their
geographical distribution.
element of WAM, the Multinational Small Arms and Ammunition Group
(MSAG) initiated a training programme on the security and stockpile
management of weapons, ammunition, and explosives for East African
states in Kenya in 2012. Participants of the ToT processes derived
from among the military, police and wildlife service sectors. Up
until March 2024, 469 participants have been trained, out of which
42 were certified as PSSM Instructors and 13 as Senior Instructors.
The map below shows their geographical distribution.
</p>
<p>
In the meantime, the need for another regional PSSM ToT process was
identified in the ECOWAS region (West Africa), which was established in
2018 and completed in 2023. Based on the identified need for a regional
trainer pool and more accountable PSSM practices, this process also took
into account lessons learned from the East Africa ToT process. Between
2018 and 2023, a total of 000 participants have been trained, out of
which 000 were certified as PSSM Instructors and 000 as Senior
Instructors. The map below shows their geographical distribution.
identified in the ECOWAS region (West Africa), which was established
in 2018 and completed in 2023. Based on the identified need for a
regional trainer pool and more accountable PSSM practices, this
process also took into account lessons learned from the East Africa
ToT process. Between 2018 and 2023, a total of 000 participants have
been trained, out of which 000 were certified as PSSM Instructors
and 000 as Senior Instructors. The map below shows their
geographical distribution.
</p>
<p>Stakeholders implementing the regional PSSM ToT trainings were:</p>
<ul>
<li>
RECSA, MSAG nations (namely the Bundeswehr Verification Centre, the
Austrian Verification Centre, Denmark, among others), IPSTC
RECSA, MSAG nations (namely the Bundeswehr Verification Centre,
the Austrian Verification Centre, Denmark, among others), IPSTC
(International Peace Support Training Centre) in Nairobi/Kenya and
bicc.
</li>
<li>ECOWAS, MSAG (the Bundeswehr Verification Centre) and bicc.</li>
</ul>
<p>
Each of these partners brings a unique skillset that complements that of
the other stakeholders.
Each of these partners brings a unique skillset that complements
that of the other stakeholders.
</p>
</div>
);
};
const Footnotes = ({ footnotes }) => {
return (
<div>
<h4>
<hr />
@ -156,6 +155,17 @@ const Footnotes = ({ footnotes }) => {
</ul>
))}
</div>
</div>
</Collapse>
<a
href="#"
onClick={() => {setOpen(!open); setIsHidden(!isHidden);}}
aria-controls="example-collapse-text"
aria-expanded={open}
>
{isHidden ? "Read more" : "Read less"}
</a>
</div>
);
};

View File

@ -0,0 +1,18 @@
import React from "react";
const Legend = () => {
return (
<div className="legend-container">
<div className="legend-item">
<div className="legend-recsa"></div>
<span>RECSA</span>
</div>
<div className="legend-item">
<div className="legend-ecowas"></div>
<span>ECOWAS</span>
</div>
</div>
);
};
export default Legend;

View File

@ -0,0 +1,52 @@
import React from "react";
import { Marker, Tooltip } from "react-leaflet";
import Person from "../../../Icons/person.svg";
import Person2 from "../../../Icons/person2.svg";
import Person3 from "../../../Icons/person3.svg";
const MarkerCustom = (props) => {
const { feature } = props;
return (
<Marker
position={[feature.properties.y, feature.properties.x]}
>
<Tooltip
direction="bottom"
offset={[-13, 27]}
opacity={1}
permanent
className="tooltip-custom"
>
<h5>{feature.properties.name}</h5>
<div>
<ul className="list-unstyled tooltip-text">
<li>
<img src={Person3} className="person-icon" /> Number of
participants trained:{" "}
<span className="tooltip-text-number">
{feature.properties["Trained-Participants"] || "-"}
</span>
</li>
<li>
<img src={Person2} className="person-icon" /> Number of PSSM
instractors:{" "}
<span className="tooltip-text-number">
{feature.properties["PSSM-Instructors"] || "-"}
</span>
</li>
<li>
<img src={Person} className="person-icon" /> Number of senior PSSM
instractors:{" "}
<span className="tooltip-text-number">
{feature.properties["PSSM-Senior-Instructors"] || "-"}
</span>
</li>
</ul>
</div>
</Tooltip>
</Marker>
);
};
export default MarkerCustom;

View File

@ -1,16 +1,33 @@
import React from "react";
import ReactDOM from 'react-dom';
import React, { useEffect } from "react";
import { MapContainer, GeoJSON, Marker, Tooltip } from "react-leaflet";
import L, { control } from "leaflet";
import { MapContainer, GeoJSON, useMap } from "react-leaflet";
import L from "leaflet";
import Africa from "../../../Data/PSSM.geojson";
import "../../../Styles/main.scss";
import Card_ from "../../UI/Card_/Card_";
import { CountrySelectedStyle, NotPSSMCountryStyle } from "./countryStyles";
import MarkerCustom from "./MarkerCustom";
import SelectMenu from "./SelectMenu";
import Legend from "./Legend";
import Person from "../../../Icons/person.svg";
import Person2 from "../../../Icons/person2.svg";
import Person3 from "../../../Icons/person3.svg";
// Custom Zoom Control Component
const CustomZoomControl = React.memo(() => {
const map = useMap();
useEffect(() => {
const zoomControl = L.control.zoom({
position: 'topright' // Change the position to bottom right
});
map.addControl(zoomControl);
// Clean up the control on component unmount
return () => {
map.removeControl(zoomControl);
};
}, [map]);
return null;
});
class PSSM extends React.Component {
constructor(props) {
@ -20,6 +37,8 @@ class PSSM extends React.Component {
africaCountries: null,
countriesNames: [],
pssmCountries: [],
recsaCountries: [],
ecowasCountries: [],
loading: true,
error: null,
selectedCountry: "",
@ -27,6 +46,7 @@ class PSSM extends React.Component {
center: [3, 15],
zoom: 4,
scrollWheelZoom: false,
zoomControl: false,
};
}
@ -48,6 +68,12 @@ class PSSM extends React.Component {
(feature) =>
feature.properties.RECSA === 1 || feature.properties.ECOWAS === 1
),
recsaCountries: data.features.filter(
(feature) => feature.properties.RECSA === 1
),
ecowasCountries: data.features.filter(
(feature) => feature.properties.ECOWAS === 1
),
loading: false,
},
() => {}
@ -58,8 +84,6 @@ class PSSM extends React.Component {
loading: false,
});
}
console.log(this.state.pssmCountries);
};
onEachFeature = (feature, layer) => {
@ -82,14 +106,26 @@ class PSSM extends React.Component {
this.setState({ selectedCountry: countryName });
};
handleCountryChange = (e) => {
const countryName = e.target.value;
const { selectedCountry } = this.state;
if (countryName === selectedCountry) {
this.setState({ selectedCountry: "" });
return;
}
this.setState({ selectedCountry: countryName });
};
render() {
const {
africaCountries,
countriesNames,
pssmCountries,
loading,
error,
selectedCountry,
recsaCountries,
ecowasCountries,
zoomControl,
} = this.state;
if (loading) {
return <div>Loading...</div>;
@ -105,6 +141,7 @@ class PSSM extends React.Component {
zoom={this.state.zoom}
style={{ width: "100%", height: "100%" }}
scrollWheelZoom={this.state.scrollWheelZoom}
zoomControl={zoomControl}
>
{africaCountries && (
<>
@ -137,39 +174,24 @@ class PSSM extends React.Component {
pssmCountries.map((feature) => {
if (feature.properties.name === selectedCountry) {
return (
<Marker
<MarkerCustom
key={feature.properties.name}
position={[feature.properties.y, feature.properties.x]}
>
<Tooltip
direction="bottom"
offset={[-13, 27]}
opacity={1}
permanent
className="tooltip-custom"
>
<h5>{feature.properties.name}</h5>
<div>
<ul className="list-unstyled tooltip-text">
<li>
<img src={Person3} className="person-icon"/> Number of participants trained:{" "}
<span className="tooltip-text-number">{feature.properties["Trained-Participants"] || "-"}</span>
</li>
<li>
<img src={Person2} className="person-icon"/> Number of PSSM instractors:{" "}
<span className="tooltip-text-number">{feature.properties["PSSM-Instructors"] || "-"}</span>
</li>
<li>
<img src={Person} className="person-icon"/> Number of senior PSSM instractors:{" "}
<span className="tooltip-text-number">{feature.properties["PSSM-Senior-Instructors"] || "-"}</span>
</li>
</ul>
</div>
</Tooltip>
</Marker>
feature={feature}
></MarkerCustom>
);
}
})}
<CustomZoomControl />
<SelectMenu
ecowasCountries={ecowasCountries}
recsaCountries={recsaCountries}
selectedCountry={selectedCountry}
handleCountryChange={this.handleCountryChange}
></SelectMenu>
<Legend />
</MapContainer>
</Card_>
);

View File

@ -0,0 +1,37 @@
import React from "react";
const SelectMenu = (props) => {
const {
ecowasCountries,
recsaCountries,
selectedCountry,
handleCountryChange,
} = props;
return (
<div className="country-select">
<select onChange={handleCountryChange} value={selectedCountry}>
<option value="">Select a country</option>
<option className="options-title" value="" disabled>
<h2>RECSA</h2>
</option>
{recsaCountries.map((feature, index) => (
<option className="" key={feature.properties.name} value={feature.properties.name}>
{feature.properties.name}
</option>
))}
<option className="options-title" value="" disabled>
ECOWAS
</option>
{ecowasCountries.map((feature, index) => (
<option className="" key={feature.properties.name} value={feature.properties.name}>
{feature.properties.name}
</option>
))}
</select>
</div>
);
};
export default SelectMenu;

View File

@ -0,0 +1,36 @@
.legend-container {
display: flex;
flex-direction: column;
font-size: 16px;
font-weight: bold;
position: absolute;
bottom: 20px;
left: 20px;
background-color: #f0f0f0;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
z-index: 1000;
}
.legend-item {
display: flex;
align-items: center;
margin-bottom: 8px; /* Adjust as needed */
}
.legend-recsa,
.legend-ecowas {
width: 30px; /* Adjust width as needed */
height: 15px; /* Adjust height as needed */
margin-right: 8px; /* Adjust space between div and span as needed */
}
.legend-recsa {
background-color: #ffffcc; /* Replace with your color */
}
.legend-ecowas {
background-color: #ffcccd; /* Replace with your color */
}

View File

@ -10,3 +10,17 @@
.person-icon{
height: 1.3rem;
}
.country-select option{
font-size: 14px;
}
.options-title{
font-size: 20px !important;
font-weight: bold;
color: $primary-accent-color;
}
.options-title-recsa{
color: #ffffcc;
}
.options-title-ecowas{
color: #ffcccd;
}

View File

@ -16,6 +16,8 @@
@import 'Layout/info_section';
@import 'Layout/_map_info_box';
@import 'Layout/_map_info_box2';
@import 'Layout/_legend';
// Import other layout partials...
// Components