From 9b7b9fb389918e7f03e28a749d36ad4d8214715a Mon Sep 17 00:00:00 2001
From: shaked-hayek <85109951+shaked-hayek@users.noreply.github.com>
Date: Sat, 26 Nov 2022 14:11:29 +0200
Subject: [PATCH 01/33] [Feat-885] Add selection for stack bar graphs (#935)
* Added stacked bar widgets a checkbox option
* Add option to choose colors when changing displayed bars
* Changed any to proper type, make number of bar generic and add function createBarWidget
* Fix bug of changed values when closing card editor
* PR review changes
* Remove redundent imports
---
public/locales/en/translation.json | 2 +
public/locales/he/translation.json | 2 +
src/components/molecules/GenericBarChart.tsx | 15 ++++--
.../widgets/CountByYearBarWidget.tsx | 12 +++--
.../widgets/CountInjuredByYearBarWidget.tsx | 12 +++--
.../molecules/widgets/WidgetWrapper.tsx | 8 +--
src/components/organisms/CardEditorDialog.tsx | 49 ++++++++++++++++---
src/components/organisms/WidgetsTemplate.tsx | 1 +
src/utils/barChart.utils.ts | 43 ++++++++++++++--
9 files changed, 117 insertions(+), 27 deletions(-)
diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json
index 20093528..2baa3f5c 100644
--- a/public/locales/en/translation.json
+++ b/public/locales/en/translation.json
@@ -73,6 +73,8 @@
"display": "Display",
"landscape": "Portrait",
"portrait": "Landscape",
+ "showAccidents": "Show Accidents",
+ "showInjured": "Show Injured",
"size": "Size",
"download": "Download as PNG"
},
diff --git a/public/locales/he/translation.json b/public/locales/he/translation.json
index 787b4590..14d82074 100644
--- a/public/locales/he/translation.json
+++ b/public/locales/he/translation.json
@@ -87,6 +87,8 @@
"display": "הצג",
"landscape": "לרוחב",
"portrait": "לאורך",
+ "showAccidents": "הצגת תאונות",
+ "showInjured": "הצגת נפגעים",
"size": "גודל",
"download": "הורד כתמונה"
},
diff --git a/src/components/molecules/GenericBarChart.tsx b/src/components/molecules/GenericBarChart.tsx
index 7da9788d..c9cdf9e5 100644
--- a/src/components/molecules/GenericBarChart.tsx
+++ b/src/components/molecules/GenericBarChart.tsx
@@ -36,6 +36,7 @@ interface ISingleBarChartProps extends IBarChartBaseProps {}
interface IMultiBarChartProps extends IBarChartBaseProps {
isStacked: boolean;
+ editorBarOptions?: Record;
}
const CustomizedLabel = (props: CustomizedLabelProps) => {
@@ -89,10 +90,18 @@ const SingleBarChart: FC = ({ data, isPercentage, textLabe
);
};
-const MultiBarChart: FC = ({ data, isPercentage, isStacked, textLabel, subtitle }) => {
+const MultiBarChart: FC = ({ data, isPercentage, isStacked, textLabel, subtitle, editorBarOptions }) => {
const yLabels = data ? Object.keys(data[0]) : [];
yLabels.splice(0, 1);
const maxBarsNum = yLabels.length;
+ const filteredColors : Record = (editorBarOptions && Object.keys(editorBarOptions).length !== 0) ?
+ Object.values(editorBarOptions).map((include: any, i: number) => {
+ if (include) {
+ return colors[i];
+ } else {
+ return false;
+ }
+ }).filter( Boolean ) : colors;
return (
= ({ data, isPercentage, isStacked,
>
{Array.from({ length: maxBarsNum }, (_, i) => {
const barStyle = {
- filter: `drop-shadow(0.2em ${isStacked ? '0' : '0.2em'} 0 ${tinycolor(colors[i]).darken().toString()})`,
+ filter: `drop-shadow(0.2em ${isStacked ? '0' : '0.2em'} 0 ${tinycolor(filteredColors[i]).darken().toString()})`,
};
return (
;
}
-const CountByYearBarWidget: FC = ({ data }) => {
- const { items, text } = data;
- const multiBarSeries = convertToBarSeries(items, text.labels_map);
- return ;
+const CountByYearBarWidget: FC = ({ data, editorBarOptions }) => {
+ const { text } = data;
+ const multiBarSeries = createBarWidget(data, editorBarOptions)
+ return ;
};
export default CountByYearBarWidget;
diff --git a/src/components/molecules/widgets/CountInjuredByYearBarWidget.tsx b/src/components/molecules/widgets/CountInjuredByYearBarWidget.tsx
index 5c5a6286..7f02b3b7 100644
--- a/src/components/molecules/widgets/CountInjuredByYearBarWidget.tsx
+++ b/src/components/molecules/widgets/CountInjuredByYearBarWidget.tsx
@@ -1,16 +1,18 @@
import React, { FC } from 'react';
import { IWidgetMultiBarData } from 'models/WidgetData';
-import { convertToBarSeries } from 'utils/barChart.utils';
+import { createBarWidget } from 'utils/barChart.utils';
import { MultiBarChart } from '../GenericBarChart';
interface IProps {
data: IWidgetMultiBarData;
+ editorBarOptions: Record;
}
-const CountInjuredByYearBarWidget: FC = ({ data }) => {
- const { items, text } = data;
- const multiBarSeries = convertToBarSeries(items, text.labels_map);
- return ;
+const CountInjuredByYearBarWidget: FC = ({ data, editorBarOptions }) => {
+ const { text } = data;
+ const multiBarSeries = createBarWidget(data, editorBarOptions);
+ return ;
};
export default CountInjuredByYearBarWidget;
diff --git a/src/components/molecules/widgets/WidgetWrapper.tsx b/src/components/molecules/widgets/WidgetWrapper.tsx
index 5db597f8..dc387555 100644
--- a/src/components/molecules/widgets/WidgetWrapper.tsx
+++ b/src/components/molecules/widgets/WidgetWrapper.tsx
@@ -1,3 +1,4 @@
+/* eslint-disable max-lines*/
import React, { FC } from 'react';
import {
IWidgetAccidentCountByRoadLight,
@@ -42,11 +43,12 @@ interface IProps {
widget: IWidgetBase;
locationText: string;
sizeOptions: any;
+ editorBarOptions: Record;
segmentText: string;
isStreet: boolean;
}
-const WidgetWrapper: FC = ({ widget, locationText, sizeOptions, segmentText, isStreet }) => {
+const WidgetWrapper: FC = ({ widget, locationText, sizeOptions, editorBarOptions, segmentText, isStreet }) => {
const { name, data } = widget;
let widgetComponent;
switch (name) {
@@ -136,11 +138,11 @@ const WidgetWrapper: FC = ({ widget, locationText, sizeOptions, segmentT
break;
}
case WidgetName.accident_count_by_accident_year: {
- widgetComponent = ;
+ widgetComponent = ;
break;
}
case WidgetName.injured_count_by_accident_year: {
- widgetComponent = ;
+ widgetComponent = ;
break;
}
case WidgetName.accident_count_by_day_night: {
diff --git a/src/components/organisms/CardEditorDialog.tsx b/src/components/organisms/CardEditorDialog.tsx
index 0b6fb09f..5382086d 100644
--- a/src/components/organisms/CardEditorDialog.tsx
+++ b/src/components/organisms/CardEditorDialog.tsx
@@ -2,29 +2,31 @@ import React, { FC, useState } from 'react';
import DialogWithHeader from '../molecules/DialogWithHeader';
import { useStore } from 'store/storeConfig';
import WidgetWrapper from 'components/molecules/widgets/WidgetWrapper';
-import { Box } from '@material-ui/core';
+import { Box, Checkbox, FormControlLabel, FormGroup } from '@material-ui/core';
import AnyWayCard, { CardSizeOptions } from 'components/molecules/card/AnyWayCard';
import { MetaTag, ErrorBoundary, Typography, Button, Slider } from 'components/atoms';
import widgetToImage from 'services/to-image.service';
import { useTranslation } from 'react-i18next';
+import { blueVioletColor } from 'style';
+import {initEditorBarOptions, barsWidgetsLabels, barsWidgetsTitle, NUM_OF_BARS} from 'utils/barChart.utils';
interface IProps {
isOpen: boolean;
onClose: () => void;
widgetName: string;
- text: string | undefined;
+ text?: string;
}
const CardEditor: FC = ({ isOpen, onClose, widgetName, text }) => {
const [cardElement, setCardElement] = useState({});
- const [size, setSize] = useState(1);
+ const [size, setSize] = useState(1)
+ const [barValues, setBarValues] = useState(initEditorBarOptions());
const { t } = useTranslation();
const store = useStore();
const { widgetsStore } = store;
const widget = widgetsStore.getWidgetsDataByName(widgetName);
const roadNumber = widgetsStore.newsFlashWidgetsMetaRoadNumber;
const dateComment = widgetsStore.newsFlashWidgetsMetaDateComment;
-
const getCardRef = (element: HTMLElement) => setCardElement(element);
const imgDownloadHandler = () => {
if (cardElement && cardElement instanceof HTMLElement) {
@@ -32,6 +34,19 @@ const CardEditor: FC = ({ isOpen, onClose, widgetName, text }) => {
}
};
+ /**
+ * When checkbox is changed, change barValues in place "location" to the
+ * negated value. When false change to true, when true change to false.
+ * @param location place in barValues object
+ * @param event not used
+ */
+ const handleCheckChange = (location: number, event: any) => {
+ setBarValues((prevState) => ({
+ ...prevState,
+ [location]: !barValues[location]
+ }));
+ };
+
const handleSizeChange = (event: any, newSize: number | number[]) => {
setSize(newSize as number);
};
@@ -45,21 +60,41 @@ const CardEditor: FC = ({ isOpen, onClose, widgetName, text }) => {
widget={widget}
locationText={widgetsStore.newsFlashWidgetsMetaLocation}
sizeOptions={sizeOptions.size}
+ editorBarOptions={barValues}
isStreet={widgetsStore.isStreet}
/>
);
+ const onCloseInitValues = () => {
+ onClose();
+ setSize(1);
+ setBarValues(initEditorBarOptions());
+ }
+
return (
-
+
+ {Object.keys(barsWidgetsLabels).includes(widgetName) ?
+
+ {t(barsWidgetsTitle[widgetName])}
+
+ {Array.from({length: NUM_OF_BARS}, (_,i) => {
+ return handleCheckChange(i, e)}/>
+ }/>
+ })}
+
+ :
+ }
- {t('cardEditor.size')}
+ {t('cardEditor.size')}
- {t('cardEditor.download')}
+ {t('cardEditor.download')}
diff --git a/src/components/organisms/WidgetsTemplate.tsx b/src/components/organisms/WidgetsTemplate.tsx
index 8ddee51a..c1dafe9e 100644
--- a/src/components/organisms/WidgetsTemplate.tsx
+++ b/src/components/organisms/WidgetsTemplate.tsx
@@ -27,6 +27,7 @@ const WidgetsTemplate: FC = () => {
locationText={widgetsStore.newsFlashWidgetsMetaLocation}
segmentText={widgetsStore.newsFlashWidgetsMetaSegmentName}
sizeOptions={sizeOptions}
+ editorBarOptions={{}}
isStreet={widgetsStore.isStreet}
/>
);
diff --git a/src/utils/barChart.utils.ts b/src/utils/barChart.utils.ts
index f2e3479c..3b4ff0a1 100644
--- a/src/utils/barChart.utils.ts
+++ b/src/utils/barChart.utils.ts
@@ -1,7 +1,22 @@
import { BarDataMap, BAR_CHART_X_LABEL } from 'components/molecules/GenericBarChart';
import { LabelsMap, MultiSeriesDataItems, SeriesDataItem } from 'models/MultiSeriesData';
+import {IWidgetMultiBarData} from "../models/WidgetData";
const getTranslatedLabel = (key: string, labelsMap: LabelsMap): string => labelsMap[key] || key;
+export const NUM_OF_BARS = 3
+
+export const barsWidgetsLabels: Record> = {
+ 'accident_count_by_accident_year':
+ ['textView.fatal.plural', 'textView.severe.plural', 'textView.light.plural'],
+ 'injured_count_by_accident_year':
+ ['textView.killed.plural', 'textView.severeInjured.plural', 'textView.lightInjured.plural'],
+}
+
+export const barsWidgetsTitle: Record = {
+ 'accident_count_by_accident_year': 'cardEditor.showAccidents',
+ 'injured_count_by_accident_year': 'cardEditor.showInjured',
+}
+
// convert input to data series, for example:
// [
// {
@@ -24,6 +39,7 @@ const getTranslatedLabel = (key: string, labelsMap: LabelsMap): string => labels
export function convertToBarSeries(
items: SeriesDataItem[] | MultiSeriesDataItems[],
labelsMap?: LabelsMap | string,
+ excludeList: any = [],
): BarDataMap[] {
return items.map((item: any) => {
const label: string = item.label_key.toString();
@@ -45,13 +61,32 @@ export function convertToBarSeries(
result['value'] = item.value;
} else {
// multi values per (stacked) bar return type is like: { xLabel: 'year 2017', light: 55, severe: 5 }
- const series = item.series;
- series.forEach((dataPoint: any) => {
- const { label_key, value } = dataPoint;
+ const series : SeriesDataItem[] = item.series;
+ series.filter((dataPoint: SeriesDataItem) => !excludeList.includes(dataPoint.label_key)).forEach(({ label_key,value }) =>{
const yLabel = getTranslatedLabel(label_key, labelsMap as LabelsMap);
result[yLabel] = Math.round(value);
- });
+ }) ;
}
return result;
});
}
+
+export function createBarWidget (
+ data: IWidgetMultiBarData,
+ editorBarOptions: Record
+): BarDataMap[] {
+ const { items, text } = data;
+ const excludeList = (Object.keys(editorBarOptions).length !== 0) ?
+ Object.values(editorBarOptions).map((include: any, index: number) => {
+ if (include) {
+ return null;
+ } else {
+ return items[0].series[index].label_key;
+ }
+ }) : []
+ return convertToBarSeries(items, text.labels_map, excludeList);
+}
+
+export function initEditorBarOptions () {
+ return Object.fromEntries(Array.from({length: NUM_OF_BARS}, (_, i) => [i, true]));
+}
From 15ff26aefce4d01dceff5c436baf877b999eabed Mon Sep 17 00:00:00 2001
From: danielsh28
Date: Sat, 26 Nov 2022 16:32:59 +0200
Subject: [PATCH 02/33] add conditional label, refactor utils (#938)
Co-authored-by: Daniel Shely <>
---
public/locales/en/translation.json | 5 ++++-
public/locales/he/translation.json | 5 +++--
src/components/molecules/LogInLinkGoogle.tsx | 2 +-
.../molecules/UserProfileHeader.tsx | 2 +-
.../molecules/map/GoogleMapsLayer.tsx | 2 +-
src/components/molecules/map/Map.tsx | 4 ++--
.../molecules/widgets/StreetViewWidget.tsx | 2 +-
.../molecules/widgets/WidgetWrapper.tsx | 3 ++-
src/{utils/utils.ts => const/generalConst.ts} | 22 +------------------
src/services/init.service.ts | 2 +-
src/services/signInWindow.ts | 2 +-
src/services/user.service.ts | 2 +-
src/services/widgets.data.service.ts | 2 +-
src/store/user.store.ts | 2 +-
src/utils/map.utils.ts | 16 ++++++++++++++
src/utils/text.utils.ts | 6 +++++
16 files changed, 43 insertions(+), 36 deletions(-)
rename src/{utils/utils.ts => const/generalConst.ts} (74%)
create mode 100644 src/utils/map.utils.ts
create mode 100644 src/utils/text.utils.ts
diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json
index 2baa3f5c..33d0bb51 100644
--- a/public/locales/en/translation.json
+++ b/public/locales/en/translation.json
@@ -49,6 +49,9 @@
"onSegment": "Road segment",
"occurred": "occurred",
"accidents": "accidents",
+ "killedAndHurt": "killed and hurt",
+ "hurt": "hurt",
+ "injured" : "casualties",
"fatal": {
"singular": "fatal",
"plural": "fatal"
@@ -110,7 +113,7 @@
},
"sideBar": "Approximate location:",
"UserProfileHeader": {
- "hallo": "Hallo",
+ "hello": "Hello",
"logout": "LOGOUT"
},
"widgets": {
diff --git a/public/locales/he/translation.json b/public/locales/he/translation.json
index 14d82074..8dfc2f06 100644
--- a/public/locales/he/translation.json
+++ b/public/locales/he/translation.json
@@ -48,7 +48,8 @@
"on": "ב",
"onSegment": "במקטע",
"occurred": "התרחשו",
- "hurt": "נהרגו ונפצעו",
+ "killedAndHurt": "נהרגו ונפצעו",
+ "hurt": "נפצעו",
"accidents": "תאונות",
"injured": "נפגעים",
"fatal": {
@@ -154,4 +155,4 @@
},
"locationIndicator": "(תוצאות חיפוש מקטע)",
"cityAndStreetIndicator": "(תוצאות חיפוש עיר ורחוב)"
-}
\ No newline at end of file
+}
diff --git a/src/components/molecules/LogInLinkGoogle.tsx b/src/components/molecules/LogInLinkGoogle.tsx
index 80eae0e9..9f1d89b8 100644
--- a/src/components/molecules/LogInLinkGoogle.tsx
+++ b/src/components/molecules/LogInLinkGoogle.tsx
@@ -1,7 +1,7 @@
import { makeStyles } from '@material-ui/core/styles';
import { oceanBlueColor, skyBlueColor } from 'style';
import React from 'react';
-import { AUTH_LOGIN_GOOGLE_URL } from 'utils/utils';
+import { AUTH_LOGIN_GOOGLE_URL } from 'const/generalConst';
import { openSignInWindow } from 'services/signInWindow';
import { useTranslation } from 'react-i18next';
const useStyles = makeStyles((theme) => ({
diff --git a/src/components/molecules/UserProfileHeader.tsx b/src/components/molecules/UserProfileHeader.tsx
index b538f8fe..877c7acf 100644
--- a/src/components/molecules/UserProfileHeader.tsx
+++ b/src/components/molecules/UserProfileHeader.tsx
@@ -8,7 +8,7 @@ import { oceanBlueColor, skyBlueColor } from 'style';
import Box from '@material-ui/core/Box';
import { Avatar } from '@material-ui/core';
import { IAnywayUserDetails } from 'services/user.service';
-import { ROLE_ADMIN_NAME } from 'utils/utils';
+import { ROLE_ADMIN_NAME } from 'const/generalConst';
import RootStore from 'store/root.store';
import { useStore } from 'store/storeConfig';
import { observer } from 'mobx-react-lite';
diff --git a/src/components/molecules/map/GoogleMapsLayer.tsx b/src/components/molecules/map/GoogleMapsLayer.tsx
index 3d10c913..c8f1403e 100644
--- a/src/components/molecules/map/GoogleMapsLayer.tsx
+++ b/src/components/molecules/map/GoogleMapsLayer.tsx
@@ -3,7 +3,7 @@ import React, { FC } from 'react';
import ReactLeafletGoogleLayer from 'react-leaflet-google-layer';
import { useParams } from 'react-router-dom';
import { MAP_STYLE } from 'style/map.style';
-import { mapApiKey } from 'utils/utils';
+import { mapApiKey } from 'const/generalConst';
const GoogleMapsLayer: FC = () => {
const { lng } = useParams<{ lng: string }>();
diff --git a/src/components/molecules/map/Map.tsx b/src/components/molecules/map/Map.tsx
index 4dd6d9ff..aff07a87 100644
--- a/src/components/molecules/map/Map.tsx
+++ b/src/components/molecules/map/Map.tsx
@@ -4,8 +4,8 @@ import { makeStyles } from '@material-ui/core/styles';
import { MapContainer } from 'react-leaflet';
import L, { LatLng } from 'leaflet';
import { IPoint } from 'models/Point';
-import { INITIAL_CENTER, INITIAL_ZOOM } from 'utils/utils';
-import { uniquePoints } from 'utils/utils';
+import { INITIAL_CENTER, INITIAL_ZOOM } from 'const/generalConst';
+import { uniquePoints } from 'utils/map.utils';
import MapViewControl from 'services/MapViewControl';
import GoogleMapsLayer from './GoogleMapsLayer';
diff --git a/src/components/molecules/widgets/StreetViewWidget.tsx b/src/components/molecules/widgets/StreetViewWidget.tsx
index a6194b59..dac60124 100644
--- a/src/components/molecules/widgets/StreetViewWidget.tsx
+++ b/src/components/molecules/widgets/StreetViewWidget.tsx
@@ -1,5 +1,5 @@
import React, { FC } from 'react';
-import { mapApiKey } from 'utils/utils';
+import { mapApiKey } from 'const/generalConst';
import ReactStreetview from 'components/molecules/widgets/streetView';
import { makeStyles } from '@material-ui/core';
import { IWidgetStreetViewData } from 'models/WidgetData';
diff --git a/src/components/molecules/widgets/WidgetWrapper.tsx b/src/components/molecules/widgets/WidgetWrapper.tsx
index dc387555..8a6d972c 100644
--- a/src/components/molecules/widgets/WidgetWrapper.tsx
+++ b/src/components/molecules/widgets/WidgetWrapper.tsx
@@ -38,6 +38,7 @@ import InjuredAccidentsWithPedestrians from './InjuredAccidentsWithPedestrians';
import { IPoint } from 'models/Point';
import { WidgetName } from 'models/WidgetName';
import KilledAndInjuredCountPerAgeGroupWidget from './KilledAndInjuredCountPerAgeGroupWidget';
+import { getInjuredBySeverityVerbLabel } from 'utils/text.utils';
interface IProps {
widget: IWidgetBase;
@@ -119,7 +120,7 @@ const WidgetWrapper: FC = ({ widget, locationText, sizeOptions, editorBa
severe: 'severeInjured',
light: 'lightInjured',
noun: 'injured',
- verb: 'hurt',
+ verb: getInjuredBySeverityVerbLabel(data as IWidgetInjuredBySeverityTextData),
}}
isStreet={isStreet}
largeNumbers={true}
diff --git a/src/utils/utils.ts b/src/const/generalConst.ts
similarity index 74%
rename from src/utils/utils.ts
rename to src/const/generalConst.ts
index b3539fb0..8bc0eb3e 100644
--- a/src/utils/utils.ts
+++ b/src/const/generalConst.ts
@@ -1,24 +1,4 @@
-import { IPoint } from 'models/Point';
-import { useLocation } from 'react-router';
-
-export function useQuery() {
- return new URLSearchParams(useLocation().search);
-}
-export function uniquePoints(points: IPoint[]) {
- const uniquePoints = new Array();
- const uniqueSet = new Set();
- // fill only unique points (not yet included in uniqueSet)
- points.forEach((p) => {
- const pointKey = `${p.latitude}:${p.longitude}`; // use x:y to create unique key
- if (!uniqueSet.has(pointKey)) {
- uniquePoints.push(p);
- uniqueSet.add(pointKey);
- }
- });
-
- return uniquePoints;
-}
-// pop up login window dimensions
+// pop up login window dimensions
export const loginPopUpDim = {
width: window.screen.width / 3.5,
diff --git a/src/services/init.service.ts b/src/services/init.service.ts
index f398c3c5..eca51d48 100644
--- a/src/services/init.service.ts
+++ b/src/services/init.service.ts
@@ -1,7 +1,7 @@
import axios from 'axios';
import { fetchNews } from './news.data.service';
import L from 'leaflet';
-import { serverUrl } from 'utils/utils';
+import { serverUrl } from 'const/generalConst';
export function initService(): Promise {
setAxiosDefaults();
diff --git a/src/services/signInWindow.ts b/src/services/signInWindow.ts
index 5486ed6c..4d60e9bb 100644
--- a/src/services/signInWindow.ts
+++ b/src/services/signInWindow.ts
@@ -1,4 +1,4 @@
-import { loginPopUpDim } from 'utils/utils';
+import { loginPopUpDim } from 'const/generalConst';
let windowObjectReference: Window | null = null;
let previousUrl: string;
diff --git a/src/services/user.service.ts b/src/services/user.service.ts
index 37c81fa0..91795e20 100644
--- a/src/services/user.service.ts
+++ b/src/services/user.service.ts
@@ -8,7 +8,7 @@ import {
GET_USERS_INFO_LIST_URL,
LOG_OUT_USER_URL, REMOVE_USER_FROM_ORG_URL,
UPDATE_USER_INFO_URL,
-} from 'utils/utils';
+} from 'const/generalConst';
import { IFormInput } from 'components/molecules/UserUpdateForm';
import { StatusCodes } from 'utils/HTTPStatuesCodes';
import { IUserInfo } from '../models/user/IUserInfo';
diff --git a/src/services/widgets.data.service.ts b/src/services/widgets.data.service.ts
index 2aa4e838..22969cce 100644
--- a/src/services/widgets.data.service.ts
+++ b/src/services/widgets.data.service.ts
@@ -1,6 +1,6 @@
import { ILocationData, IWidgetBase } from 'models/WidgetData';
import axios from 'axios';
-import { showOnlyOperCards, SHOW_MOCK } from 'utils/utils';
+import { showOnlyOperCards, SHOW_MOCK } from 'const/generalConst';
import { operationalCards } from 'const/cards.const';
import { getVerifiedWidgetsData } from './data.verification/data.verification.service';
diff --git a/src/store/user.store.ts b/src/store/user.store.ts
index 6e68b00c..f96e2444 100644
--- a/src/store/user.store.ts
+++ b/src/store/user.store.ts
@@ -11,7 +11,7 @@ import {
updateUserOrganization,
} from 'services/user.service';
import { IUserInfo } from 'models/user/IUserInfo';
-import { ROLE_ADMIN_NAME } from 'utils/utils';
+import { ROLE_ADMIN_NAME } from 'const/generalConst';
import { IFormInput } from 'components/molecules/UserUpdateForm';
export default class UserStore {
diff --git a/src/utils/map.utils.ts b/src/utils/map.utils.ts
new file mode 100644
index 00000000..0f532908
--- /dev/null
+++ b/src/utils/map.utils.ts
@@ -0,0 +1,16 @@
+import { IPoint } from '../models/Point';
+
+export function uniquePoints(points: IPoint[]) {
+ const uniquePoints = new Array();
+ const uniqueSet = new Set();
+ // fill only unique points (not yet included in uniqueSet)
+ points.forEach((p) => {
+ const pointKey = `${p.latitude}:${p.longitude}`; // use x:y to create unique key
+ if (!uniqueSet.has(pointKey)) {
+ uniquePoints.push(p);
+ uniqueSet.add(pointKey);
+ }
+ });
+
+ return uniquePoints;
+};
diff --git a/src/utils/text.utils.ts b/src/utils/text.utils.ts
new file mode 100644
index 00000000..7dbfa252
--- /dev/null
+++ b/src/utils/text.utils.ts
@@ -0,0 +1,6 @@
+import { IWidgetInjuredBySeverityTextData } from '../models/WidgetData';
+
+
+export const getInjuredBySeverityVerbLabel = (data : IWidgetInjuredBySeverityTextData) : string => {
+ return data.items.killed_count ? 'killedAndHurt' : 'hurt';
+}
From 57e078802a0aeee30eb7a072b0423e2e39ba6858 Mon Sep 17 00:00:00 2001
From: Atalya Alon <20992625+atalyaalon@users.noreply.github.com>
Date: Wed, 8 Feb 2023 21:02:49 +0200
Subject: [PATCH 03/33] Update .env.staging (#947)
---
.env.staging | 1 +
1 file changed, 1 insertion(+)
diff --git a/.env.staging b/.env.staging
index 61891e17..ce340941 100644
--- a/.env.staging
+++ b/.env.staging
@@ -1,6 +1,7 @@
# override .env, .env.production
# environment flags
REACT_APP_ENV=staging
+REACT_APP_BASE_URL=https://dev.anyway.co.il/
# Behaviour
REACT_APP_SHOW_META_TAGS=true
From 1a372a2db8c8a7c6236e3ae6a059328e0ea1f071 Mon Sep 17 00:00:00 2001
From: carmelp16 <46032304+carmelp16@users.noreply.github.com>
Date: Wed, 1 Mar 2023 19:34:30 +0200
Subject: [PATCH 04/33] Add critical indication (#948)
* Added image
* Added critical icon based on field value
* Added critical option to the filter panel
* Added enum value
* Had to increase width
* Added local critical filter
* Added field to model
---
src/assets/critical.jpg | Bin 0 -> 2475 bytes
.../molecules/NewsFlashFilterPanel.tsx | 5 +++
src/components/organisms/News.tsx | 14 +++++---
src/models/NewFlash.ts | 1 +
src/models/SourceFilter.ts | 1 +
src/pages/HomePage.tsx | 2 +-
src/store/news-flash-store.ts | 34 +++++++++++++-----
7 files changed, 43 insertions(+), 14 deletions(-)
create mode 100755 src/assets/critical.jpg
diff --git a/src/assets/critical.jpg b/src/assets/critical.jpg
new file mode 100755
index 0000000000000000000000000000000000000000..b6d2b5024d1b741f481e349f446a6ecf8a372b91
GIT binary patch
literal 2475
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
CmwYJz
literal 0
HcmV?d00001
diff --git a/src/components/molecules/NewsFlashFilterPanel.tsx b/src/components/molecules/NewsFlashFilterPanel.tsx
index d9f6ee3f..abc04c8c 100644
--- a/src/components/molecules/NewsFlashFilterPanel.tsx
+++ b/src/components/molecules/NewsFlashFilterPanel.tsx
@@ -5,6 +5,7 @@ import { silverSmokeColor, oceanBlueColor } from 'style';
import ynetLogo from 'assets/ynet-website-logo.svg';
import wallaLogo from 'assets/walla-logo.svg';
import madaLogo from 'assets/mada-logo.svg';
+import criticalLogo from 'assets/critical.jpg';
import { AnyWayButton } from 'components/atoms/AnyWayButton';
import RootStore from 'store/root.store';
import { useStore } from 'store/storeConfig';
@@ -16,6 +17,7 @@ const useStyles = makeStyles({
image: {
maxWidth: '50px',
maxHeight: '35px',
+ mixBlendMode: "multiply"
},
button: {
height: '50px',
@@ -59,6 +61,9 @@ const NewsFlashFilterPanel: FC = () => {
case SourceFilterEnum.mda: {
return madaLogo;
}
+ case SourceFilterEnum.critical: {
+ return criticalLogo;
+ }
}
};
diff --git a/src/components/organisms/News.tsx b/src/components/organisms/News.tsx
index 2e7035ab..0bc7a73e 100644
--- a/src/components/organisms/News.tsx
+++ b/src/components/organisms/News.tsx
@@ -10,6 +10,7 @@ import { dateFormat } from 'utils/time.utils';
import { useLocale } from 'hooks/date.hooks';
import LocationSearchIndicator from 'components/molecules/LocationSearchIndicator';
import { IRouteProps } from 'models/Route';
+import CriticalIcon from 'assets/critical.jpg';
const useStyles = makeStyles({
container: {},
@@ -40,11 +41,14 @@ const News: FC = () => {
return (
-
-
- {date}, {news.display_source}
-
-
+
+
+
+ {date}, {news.display_source}
+
+
+ {(news.hasOwnProperty('critical') && news.critical) && }
+
{news.title}
diff --git a/src/models/NewFlash.ts b/src/models/NewFlash.ts
index 3b882243..2a926086 100644
--- a/src/models/NewFlash.ts
+++ b/src/models/NewFlash.ts
@@ -13,4 +13,5 @@ export interface INewsFlash {
location: string;
title: string;
source: string;
+ critical?: boolean;
}
diff --git a/src/models/SourceFilter.ts b/src/models/SourceFilter.ts
index c0ef1b6c..666d3d37 100644
--- a/src/models/SourceFilter.ts
+++ b/src/models/SourceFilter.ts
@@ -3,4 +3,5 @@ export enum SourceFilterEnum {
ynet = 'ynet',
walla = 'walla',
mda = 'twitter',
+ critical = 'critical'
}
diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx
index 69bce348..1c151a3a 100644
--- a/src/pages/HomePage.tsx
+++ b/src/pages/HomePage.tsx
@@ -61,7 +61,7 @@ const HomePage: FC = () => {
return (
-
+
diff --git a/src/store/news-flash-store.ts b/src/store/news-flash-store.ts
index c8636655..4269828e 100644
--- a/src/store/news-flash-store.ts
+++ b/src/store/news-flash-store.ts
@@ -5,8 +5,15 @@ import { INewsFlash } from 'models/NewFlash';
import { IPoint } from 'models/Point';
import RootStore from './root.store';
+function filterByCritical(newsFlashCollection: Array): Array {
+ return newsFlashCollection.filter(news => news.hasOwnProperty("critical") && news.critical);
+}
+
const DEFAULT_TIME_FILTER = 5;
const DEFAULT_LOCATION = { latitude: 32.0853, longitude: 34.7818 };
+const LOCAL_FILTERS: { [key in SourceFilterEnum]?: (newsFlashCollection: Array) => Array } = {
+ [SourceFilterEnum.critical]: filterByCritical
+}
export default class NewsFlashStore {
rootStore: RootStore;
@@ -88,23 +95,34 @@ export default class NewsFlashStore {
if (filter !== this.newsFlashActiveFilter) {
runInAction(() => {
this.newsFlashActiveFilter = filter;
- this.newsFlashCollection = [];
this.newsFlashFetchOffSet = 0;
});
+ if (!(filter in LOCAL_FILTERS)) {
+ runInAction(() => {
+ this.newsFlashCollection = [];
+ });
+ }
this.filterNewsFlashCollection();
}
}
filterNewsFlashCollection(): void {
runInAction(() => (this.newsFlashLoading = true));
- fetchNews(this.newsFlashActiveFilter, this.newsFlashFetchOffSet).then((data: any) => {
+ if (this.newsFlashActiveFilter in LOCAL_FILTERS) {
+ const filterMethod = LOCAL_FILTERS[this.newsFlashActiveFilter];
+ const filtered = filterMethod && filterMethod(this.newsFlashCollection);
+ runInAction(() => (this.newsFlashCollection = [...(filtered || [])]));
runInAction(() => (this.newsFlashLoading = false));
- if (data) {
- runInAction(() => (this.newsFlashCollection = [...this.newsFlashCollection, ...data]));
- } else {
- console.error(`filterNewsFlashCollection(filter:${this.newsFlashActiveFilter}) invalid data:`, data);
- }
- });
+ } else {
+ fetchNews(this.newsFlashActiveFilter, this.newsFlashFetchOffSet).then((data: any) => {
+ runInAction(() => (this.newsFlashLoading = false));
+ if (data) {
+ runInAction(() => (this.newsFlashCollection = [...this.newsFlashCollection, ...data]));
+ } else {
+ console.error(`filterNewsFlashCollection(filter:${this.newsFlashActiveFilter}) invalid data:`, data);
+ }
+ });
+ }
}
infiniteFetchLimit(fetchSize: number): void {
runInAction(() => (this.newsFlashFetchOffSet += fetchSize));
From dcdb07ddc6f95f8a21a65d1d9856a9a9a6a75917 Mon Sep 17 00:00:00 2001
From: EyalIlan <55767736+EyalIlan@users.noreply.github.com>
Date: Fri, 3 Mar 2023 11:21:21 +0200
Subject: [PATCH 05/33] add alt attrinbte on image tag (#951)
---
src/components/organisms/News.tsx | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/components/organisms/News.tsx b/src/components/organisms/News.tsx
index 0bc7a73e..a26cbeb7 100644
--- a/src/components/organisms/News.tsx
+++ b/src/components/organisms/News.tsx
@@ -21,7 +21,8 @@ const useStyles = makeStyles({
backgroundColor: silverSmokeColor,
},
});
-
+//
+
const News: FC = () => {
const store: RootStore = useStore();
const classes = useStyles();
@@ -47,7 +48,7 @@ const News: FC = () => {
{date}, {news.display_source}
- {(news.hasOwnProperty('critical') && news.critical) && }
+ {(news.hasOwnProperty('critical') && news.critical) && }
{news.title}
From a3833ea4d6520a48b4feba19b8277c90312cb1c1 Mon Sep 17 00:00:00 2001
From: Atalya Alon <20992625+atalyaalon@users.noreply.github.com>
Date: Sun, 5 Mar 2023 18:10:52 +0200
Subject: [PATCH 06/33] Update .env.staging (#952)
---
.env.staging | 1 -
1 file changed, 1 deletion(-)
diff --git a/.env.staging b/.env.staging
index ce340941..61891e17 100644
--- a/.env.staging
+++ b/.env.staging
@@ -1,7 +1,6 @@
# override .env, .env.production
# environment flags
REACT_APP_ENV=staging
-REACT_APP_BASE_URL=https://dev.anyway.co.il/
# Behaviour
REACT_APP_SHOW_META_TAGS=true
From 8c0fd687dd35103c971168d0ff7892b7d54a7629 Mon Sep 17 00:00:00 2001
From: carmelp16 <46032304+carmelp16@users.noreply.github.com>
Date: Wed, 22 Mar 2023 18:47:30 +0200
Subject: [PATCH 07/33] Make critical filter non local (#958)
* sufficient condition
* Use object for fetch args
* Send params in object format
* Make fields optional
* don't use "any" type hint
---
src/components/organisms/News.tsx | 2 +-
src/services/news.data.service.ts | 11 ++++++++++-
src/store/news-flash-store.ts | 20 +++++++++++---------
3 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/src/components/organisms/News.tsx b/src/components/organisms/News.tsx
index a26cbeb7..4865b853 100644
--- a/src/components/organisms/News.tsx
+++ b/src/components/organisms/News.tsx
@@ -48,7 +48,7 @@ const News: FC = () => {
{date}, {news.display_source}
- {(news.hasOwnProperty('critical') && news.critical) && }
+ {news.critical && }
{news.title}
diff --git a/src/services/news.data.service.ts b/src/services/news.data.service.ts
index d2f21ef0..b5353895 100644
--- a/src/services/news.data.service.ts
+++ b/src/services/news.data.service.ts
@@ -17,8 +17,14 @@ const errorNews: INewsFlash = {
};
const NEWS_FLASH_API: string = '/api/news-flash';
+export interface IFetchNewsQueryParams {
+ source?: string;
+ offSet?: number;
+ limit?: number;
+ critical?: boolean | null;
+};
-export function fetchNews(source = '', offSet = 0, limit = 100): Promise {
+export function fetchNews({source = '', offSet = 0, limit = 100, critical = null}: IFetchNewsQueryParams = {}): Promise {
const query = [];
if (source) {
query.push(`source=${source}`);
@@ -26,6 +32,9 @@ export function fetchNews(source = '', offSet = 0, limit = 100): Promise {
if (limit) {
query.push(`limit=${limit}`);
}
+ if (critical !== null) {
+ query.push(`critical=${critical}`);
+ }
query.push(`offset=${offSet}`);
query.push('resolution=suburban_road');
diff --git a/src/store/news-flash-store.ts b/src/store/news-flash-store.ts
index 4269828e..6f049440 100644
--- a/src/store/news-flash-store.ts
+++ b/src/store/news-flash-store.ts
@@ -1,19 +1,13 @@
import { runInAction, makeAutoObservable } from 'mobx';
import { SourceFilterEnum } from 'models/SourceFilter';
-import { fetchNews } from 'services/news.data.service';
+import { fetchNews, IFetchNewsQueryParams } from 'services/news.data.service';
import { INewsFlash } from 'models/NewFlash';
import { IPoint } from 'models/Point';
import RootStore from './root.store';
-function filterByCritical(newsFlashCollection: Array): Array {
- return newsFlashCollection.filter(news => news.hasOwnProperty("critical") && news.critical);
-}
-
const DEFAULT_TIME_FILTER = 5;
const DEFAULT_LOCATION = { latitude: 32.0853, longitude: 34.7818 };
-const LOCAL_FILTERS: { [key in SourceFilterEnum]?: (newsFlashCollection: Array) => Array } = {
- [SourceFilterEnum.critical]: filterByCritical
-}
+const LOCAL_FILTERS: { [key in SourceFilterEnum]?: (newsFlashCollection: Array) => Array } = {};
export default class NewsFlashStore {
rootStore: RootStore;
@@ -114,7 +108,15 @@ export default class NewsFlashStore {
runInAction(() => (this.newsFlashCollection = [...(filtered || [])]));
runInAction(() => (this.newsFlashLoading = false));
} else {
- fetchNews(this.newsFlashActiveFilter, this.newsFlashFetchOffSet).then((data: any) => {
+ const queryParams: IFetchNewsQueryParams = {
+ offSet: this.newsFlashFetchOffSet
+ };
+ if (this.newsFlashActiveFilter == "critical") {
+ queryParams["critical"] = true;
+ } else {
+ queryParams["source"] = this.newsFlashActiveFilter;
+ }
+ fetchNews(queryParams).then((data: any) => {
runInAction(() => (this.newsFlashLoading = false));
if (data) {
runInAction(() => (this.newsFlashCollection = [...this.newsFlashCollection, ...data]));
From 4e536abe031513b28d014aba94e828fe2e92dc58 Mon Sep 17 00:00:00 2001
From: Atalya Alon <20992625+atalyaalon@users.noreply.github.com>
Date: Tue, 25 Apr 2023 19:04:28 +0300
Subject: [PATCH 08/33] Update News.tsx (#961)
---
src/components/organisms/News.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/organisms/News.tsx b/src/components/organisms/News.tsx
index 4865b853..4079c06d 100644
--- a/src/components/organisms/News.tsx
+++ b/src/components/organisms/News.tsx
@@ -48,7 +48,7 @@ const News: FC = () => {
{date}, {news.display_source}
- {news.critical && }
+ {news.critical && }
{news.title}
From dd9febfa54958fa8e38675025111047024805d73 Mon Sep 17 00:00:00 2001
From: Atalya Alon <20992625+atalyaalon@users.noreply.github.com>
Date: Tue, 25 Apr 2023 19:04:51 +0300
Subject: [PATCH 09/33] Update news-flash-store.ts (#962)
---
src/store/news-flash-store.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/store/news-flash-store.ts b/src/store/news-flash-store.ts
index 6f049440..86e0d62e 100644
--- a/src/store/news-flash-store.ts
+++ b/src/store/news-flash-store.ts
@@ -111,7 +111,7 @@ export default class NewsFlashStore {
const queryParams: IFetchNewsQueryParams = {
offSet: this.newsFlashFetchOffSet
};
- if (this.newsFlashActiveFilter == "critical") {
+ if (this.newsFlashActiveFilter === "critical") {
queryParams["critical"] = true;
} else {
queryParams["source"] = this.newsFlashActiveFilter;
From 7b67d0753bf582e333b25a18dc4b0996bbe89e62 Mon Sep 17 00:00:00 2001
From: Atalya Alon <20992625+atalyaalon@users.noreply.github.com>
Date: Tue, 25 Apr 2023 19:10:22 +0300
Subject: [PATCH 10/33] Update News.tsx
---
src/components/organisms/News.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/organisms/News.tsx b/src/components/organisms/News.tsx
index 4079c06d..0325e851 100644
--- a/src/components/organisms/News.tsx
+++ b/src/components/organisms/News.tsx
@@ -48,7 +48,7 @@ const News: FC = () => {
{date}, {news.display_source}
- {news.critical && }
+ {news.critical && }
{news.title}
From a06502e35e4f0c59d83ae842dee61000ffd5a07c Mon Sep 17 00:00:00 2001
From: Atalya Alon <20992625+atalyaalon@users.noreply.github.com>
Date: Mon, 29 May 2023 17:58:38 +0300
Subject: [PATCH 11/33] Update thank-you-names.csv
---
public/thank-you-names.csv | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/public/thank-you-names.csv b/public/thank-you-names.csv
index 4b857e41..e8b52315 100755
--- a/public/thank-you-names.csv
+++ b/public/thank-you-names.csv
@@ -96,6 +96,7 @@ Name
עינת קדרון
עמוס הוכמן
ערן גלבוע
+פועה בוגרד
קוסטיה קלינובסקי
רביע עפאן
רון פייביש
@@ -111,4 +112,5 @@ Name
שני וינשטוק
שקד זיכלינסקי
שקד חייאק
-תמר קליר
\ No newline at end of file
+תהילה נחמיה
+תמר קליר
From 61a492ed172b7ed66a137fb41b87aaafbe532575 Mon Sep 17 00:00:00 2001
From: Atalya Alon <20992625+atalyaalon@users.noreply.github.com>
Date: Sat, 24 Jun 2023 21:43:06 +0300
Subject: [PATCH 12/33] transaction dialog box (#966)
Co-authored-by: EyalIlan
---
public/locales/he/translation.json | 3 +
src/components/molecules/card/AnyWayCard.tsx | 33 +++++++-
src/components/organisms/CardEditorDialog.tsx | 1 +
src/components/organisms/TextBox.tsx | 76 +++++++++++++++++++
src/components/organisms/WidgetsTemplate.tsx | 3 +-
5 files changed, 111 insertions(+), 5 deletions(-)
create mode 100644 src/components/organisms/TextBox.tsx
diff --git a/public/locales/he/translation.json b/public/locales/he/translation.json
index 8dfc2f06..f8b5519c 100644
--- a/public/locales/he/translation.json
+++ b/public/locales/he/translation.json
@@ -108,6 +108,9 @@
"filterPanel": {
"all": "הכל"
},
+ "infografic" :{
+ "transaction":"תמלול אינפוגרפיקה"
+ },
"header": {
"Search": "חיפוש",
"User Greeting": "שלום",
diff --git a/src/components/molecules/card/AnyWayCard.tsx b/src/components/molecules/card/AnyWayCard.tsx
index d95a9f03..594ab25a 100644
--- a/src/components/molecules/card/AnyWayCard.tsx
+++ b/src/components/molecules/card/AnyWayCard.tsx
@@ -2,12 +2,14 @@ import React, { FC, useState } from 'react';
import { Card, CardContent, Box } from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles';
import widgetToImage from 'services/to-image.service';
+// TEXT BOX COMPONENT ADD FEATURE
+import TextBox from 'components/organisms/TextBox'
import { AnyWayButton } from 'components/atoms/AnyWayButton';
import Tooltip from '@material-ui/core/Tooltip';
import GetAppOutlinedIcon from '@material-ui/icons/GetAppOutlined';
import SettingsOverscanIcon from '@material-ui/icons/SettingsOverscan';
import InfoOutlinedIcon from '@material-ui/icons/InfoOutlined';
-
+import TitleIcon from '@material-ui/icons/Title';
import { fontFamilyString } from 'style';
import CardHeader from './CardHeader';
import SocialShare from 'components/atoms/SocialShare';
@@ -35,6 +37,7 @@ interface IProps {
information?: string;
organizationData?: OrgLogoData;
subtitle?: string;
+ BoxText?:string;
}
const getSizeFactor = (options: CardSizeOptions | undefined): number => (options?.size ? options.size : DEFAULTE_SIZE);
@@ -76,10 +79,17 @@ const AnyWayCard: FC = ({
information,
organizationData,
subtitle,
+ BoxText
}) => {
const [element, setElement] = useState({});
const [isOpen, setOpen] = useState(false);
- const handleCardEditorOpen = () => setOpen(true);
+ const [widgateOpen,SetWidgetOpen] = useState('')
+
+ const handleCardEditorOpen = (name:string) =>{
+ SetWidgetOpen(name)
+ setOpen(true)
+ };
+
const handleCardEditorClose = () => setOpen(false);
const variant = getWidgetVariant(widgetName);
const factor = getSizeFactor(sizeOptions);
@@ -91,12 +101,24 @@ const AnyWayCard: FC = ({
widgetToImage(widgetName, element);
}
};
+
+ let Widget;
+
+ switch(widgateOpen){
+
+ case 'TextBox':
+ Widget =
+ break
+ case 'CardEditor':
+ Widget =
+ }
+
const buttons = !actionButtons ? null : (
<>
-
+ {handleCardEditorOpen('CardEditor')}}>
{information && (
@@ -108,6 +130,9 @@ const AnyWayCard: FC = ({
)}
+ {handleCardEditorOpen('TextBox')}}>
+
+
>
);
@@ -152,7 +177,7 @@ const AnyWayCard: FC = ({
/>
)}
-
+ {Widget}
diff --git a/src/components/organisms/CardEditorDialog.tsx b/src/components/organisms/CardEditorDialog.tsx
index 5382086d..2a06314d 100644
--- a/src/components/organisms/CardEditorDialog.tsx
+++ b/src/components/organisms/CardEditorDialog.tsx
@@ -8,6 +8,7 @@ import { MetaTag, ErrorBoundary, Typography, Button, Slider } from 'components/a
import widgetToImage from 'services/to-image.service';
import { useTranslation } from 'react-i18next';
import { blueVioletColor } from 'style';
+
import {initEditorBarOptions, barsWidgetsLabels, barsWidgetsTitle, NUM_OF_BARS} from 'utils/barChart.utils';
interface IProps {
diff --git a/src/components/organisms/TextBox.tsx b/src/components/organisms/TextBox.tsx
new file mode 100644
index 00000000..e74ec544
--- /dev/null
+++ b/src/components/organisms/TextBox.tsx
@@ -0,0 +1,76 @@
+import React from 'react'
+import DialogWithHeader from '../molecules/DialogWithHeader';
+import { AnyWayButton } from 'components/atoms/AnyWayButton';
+import { Box, makeStyles} from '@material-ui/core'
+import { useTranslation } from 'react-i18next';
+import { Typography } from 'components/atoms';
+import { transparent } from 'style';
+
+
+interface IProps {
+ isOpen: boolean;
+ onClose: () => void;
+ widgetName: string;
+ text: string | undefined;
+}
+const TextBox: React.FC = ({ isOpen,text,onClose}) => {
+
+ console.log('transaction ',text);
+
+
+ const useStyles = makeStyles((theme) => ({
+ text: {
+ position: 'relative', // for meta tags
+ boxSizing: 'border-box',
+ zIndex: 0,
+ margin: '20px 0',
+ textAlign: 'center',
+ lineHeight: 1.7
+ },
+ root: {
+ display: 'flex',
+ flexDirection:'column',
+ alignItems:'center',
+ boxSizing:'border-box',
+ padding:20
+ },
+ button: {
+ margin: '20px 0',
+ '&:hover': {
+ backgroundColor: transparent,
+ },
+ },
+ img:{
+ height:'100px',
+ width:'100px'
+ }
+
+
+ }));
+
+ const { t } = useTranslation();
+ const onCloseInitValues = () => {
+ onClose();
+ }
+
+ const classes = useStyles();
+
+ return (
+
+
+
+
+ {text}
+
+
+
+ {navigator.clipboard.writeText(text?text:'asdsadasd')}} className={classes.button} >
+
+
+
+
+
+ )
+}
+
+export default TextBox
\ No newline at end of file
diff --git a/src/components/organisms/WidgetsTemplate.tsx b/src/components/organisms/WidgetsTemplate.tsx
index c1dafe9e..479dabbc 100644
--- a/src/components/organisms/WidgetsTemplate.tsx
+++ b/src/components/organisms/WidgetsTemplate.tsx
@@ -31,15 +31,16 @@ const WidgetsTemplate: FC = () => {
isStreet={widgetsStore.isStreet}
/>
);
- console.log(widget.data?.text?.subtitle);
if (!widgetComponent) {
return null;
}
+
return (
Date: Wed, 12 Jul 2023 19:23:55 +0300
Subject: [PATCH 13/33] [Feat-925] Add location approval feature (#969)
* initial feature commit with icon and new field
* Added icon choice and display
* Move critical icon
* Add location change button
* Make critical icon transperent
* replace critical.gif with svg
* Window open pressing button, seperated newsFlash comp to new file
* Added user info
* Status icon and buttons
* Added map choice (need to finish with saving data)
* Saving location and qualificaion data
* Added manual option for location qualification and added user change
* Fix responsibilty issue between the two files
* Split Search city to 2 files
* Spacing and page look
* Changed initialLocation to be a function, and improved onClose location window
* Split radio buttons to seperate file
* updated put function for news flash
---------
Co-authored-by: Daniel Shely <>
---
public/locales/en/translation.json | 15 ++
public/locales/he/translation.json | 15 ++
public/thank-you-names.csv | 2 +-
src/assets/cancel_red_24dp.svg | 4 +
src/assets/check_blue_24dp.svg | 3 +
src/assets/critical.jpg | Bin 2475 -> 0 bytes
src/assets/critical.svg | 3 +
src/cancel_black_24dp.svg | 2 +
src/components/atoms/Button.tsx | 9 +
.../molecules/ApproveLocationRadioButtons.tsx | 43 ++++
src/components/molecules/LocationSelect.tsx | 12 +-
src/components/molecules/MapDialog.tsx | 32 +--
src/components/molecules/NewsFlashComp.tsx | 85 ++++++++
.../molecules/NewsFlashFilterPanel.tsx | 2 +-
.../molecules/SearchCityAndStreet.tsx | 75 +++++++
.../molecules/SearchCityAndStreetScreen.tsx | 92 ++++----
.../organisms/LocationApproveWindow.tsx | 202 ++++++++++++++++++
src/components/organisms/News.tsx | 41 +---
src/const/generalConst.ts | 3 +-
src/models/NewFlash.ts | 1 +
src/models/WidgetData.ts | 5 +
src/services/news.data.service.ts | 20 ++
22 files changed, 542 insertions(+), 124 deletions(-)
create mode 100644 src/assets/cancel_red_24dp.svg
create mode 100644 src/assets/check_blue_24dp.svg
delete mode 100755 src/assets/critical.jpg
create mode 100644 src/assets/critical.svg
create mode 100644 src/cancel_black_24dp.svg
create mode 100644 src/components/molecules/ApproveLocationRadioButtons.tsx
create mode 100644 src/components/molecules/NewsFlashComp.tsx
create mode 100644 src/components/molecules/SearchCityAndStreet.tsx
create mode 100644 src/components/organisms/LocationApproveWindow.tsx
diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json
index 33d0bb51..58dc1af6 100644
--- a/public/locales/en/translation.json
+++ b/public/locales/en/translation.json
@@ -81,6 +81,20 @@
"size": "Size",
"download": "Download as PNG"
},
+ "LocationApprove": {
+ "title": "Change/Approve location",
+ "newsFlash": "News flash",
+ "accident": "Location of accident",
+ "changeAllowed": "Can choose location on the map or choose city and ",
+ "updater": "User updating",
+ "status": "Status",
+ "pleaseMark": "please choose",
+ "verifyLocation": "Approve segment",
+ "rejectLocation": "Reject segment",
+ "segment": "Segment",
+ "approveButton": "Approve",
+ "cancelButton": "Cancel"
+ },
"labelPosition": "Label Position",
"table": {
"labels": ["Date", "Hour", "Type", "Killed", "Severe", "Light"]
@@ -112,6 +126,7 @@
"edit": "edit"
},
"sideBar": "Approximate location:",
+ "changeLocationButton": "Change/Approve location",
"UserProfileHeader": {
"hello": "Hello",
"logout": "LOGOUT"
diff --git a/public/locales/he/translation.json b/public/locales/he/translation.json
index f8b5519c..d334f32b 100644
--- a/public/locales/he/translation.json
+++ b/public/locales/he/translation.json
@@ -93,6 +93,20 @@
"size": "גודל",
"download": "הורד כתמונה"
},
+ "LocationApprove": {
+ "title": "שינוי/אישור מיקום",
+ "newsFlash": "המבזק",
+ "accident": "מיקום התאונה",
+ "changeAllowed": "ניתן לשנות מיקום על המפה או לבחור יישוב ורחוב",
+ "updater": "הגורם המעדכן",
+ "status": "סטטוס",
+ "pleaseMark": "נא לסמן",
+ "verifyLocation": "זיהוי מקטע ודאי",
+ "rejectLocation": "מקטע לא זוהה נכון",
+ "segment": "המקטע",
+ "approveButton": "אישור",
+ "cancelButton": "ביטול"
+ },
"labelPosition": "מיקום תווית",
"table": {
"labels": [
@@ -118,6 +132,7 @@
"management": "ניהול"
},
"sideBar": "מיקום משוער:",
+ "changeLocationButton": "שינוי/אישור מיקום",
"UserProfileHeader": {
"hallo": "שלום",
"logout": "התנתקות"
diff --git a/public/thank-you-names.csv b/public/thank-you-names.csv
index e8b52315..a6710f4e 100755
--- a/public/thank-you-names.csv
+++ b/public/thank-you-names.csv
@@ -111,6 +111,6 @@ Name
שלומי ברוך
שני וינשטוק
שקד זיכלינסקי
-שקד חייאק
+שקד חייק
תהילה נחמיה
תמר קליר
diff --git a/src/assets/cancel_red_24dp.svg b/src/assets/cancel_red_24dp.svg
new file mode 100644
index 00000000..a0ace1b4
--- /dev/null
+++ b/src/assets/cancel_red_24dp.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/assets/check_blue_24dp.svg b/src/assets/check_blue_24dp.svg
new file mode 100644
index 00000000..d1b67278
--- /dev/null
+++ b/src/assets/check_blue_24dp.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/critical.jpg b/src/assets/critical.jpg
deleted file mode 100755
index b6d2b5024d1b741f481e349f446a6ecf8a372b91..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 2475
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
CmwYJz
diff --git a/src/assets/critical.svg b/src/assets/critical.svg
new file mode 100644
index 00000000..922da557
--- /dev/null
+++ b/src/assets/critical.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/cancel_black_24dp.svg b/src/cancel_black_24dp.svg
new file mode 100644
index 00000000..38bd077c
--- /dev/null
+++ b/src/cancel_black_24dp.svg
@@ -0,0 +1,2 @@
+
diff --git a/src/components/atoms/Button.tsx b/src/components/atoms/Button.tsx
index a071993e..f7839d7a 100644
--- a/src/components/atoms/Button.tsx
+++ b/src/components/atoms/Button.tsx
@@ -5,6 +5,7 @@ interface IProps {
onClick?: () => void;
isSubmit?: boolean;
disabled?: boolean;
+ buttonHeight?: number;
}
// todo: make standard buttons for entire app
@@ -14,6 +15,13 @@ const StandardButton: FC = ({ isSubmit = false, onClick, children, disab
);
+const SmallButton: FC = ({ isSubmit = false, onClick, children, buttonHeight, disabled = false }) => (
+
+ {children}
+
+);
+
const OutlinedButton: FC = ({ isSubmit = false, onClick, children }) => (
{children}
@@ -33,6 +41,7 @@ const Button = {
Icon: IconButton,
Outlined: OutlinedButton,
Text: TextButton,
+ Small: SmallButton,
};
export default Button;
diff --git a/src/components/molecules/ApproveLocationRadioButtons.tsx b/src/components/molecules/ApproveLocationRadioButtons.tsx
new file mode 100644
index 00000000..91d1ba81
--- /dev/null
+++ b/src/components/molecules/ApproveLocationRadioButtons.tsx
@@ -0,0 +1,43 @@
+import {FormControl, FormControlLabel, makeStyles, Radio, RadioGroup} from "@material-ui/core";
+import React, {FC} from "react";
+import {useTranslation} from "react-i18next";
+import {ReactComponent as CheckCircleIcon} from "assets/check_blue_24dp.svg";
+import {oceanBlueColor, roseColor, silverGrayColor} from "style";
+import {ReactComponent as CancelCircleIcon} from "assets/cancel_red_24dp.svg";
+
+
+interface IProps {
+ handleApproveStatusChange: (event : React.ChangeEvent) => void;
+ defaultValue: string;
+}
+
+const useStyles = makeStyles({
+ icon: {
+ height: 23,
+ width:23,
+ },
+});
+
+const ApproveLocationRadioButtons: FC = ({ handleApproveStatusChange, defaultValue}) => {
+ const { t } = useTranslation();
+ const classes = useStyles();
+
+ const checkedApproveIcon =
+ const uncheckedApproveIcon =
+ const checkedRejectIcon =
+ const uncheckedRejectIcon =
+
+ return (
+
+ }
+ label={t('LocationApprove.verifyLocation')} />
+ }
+ label={t('LocationApprove.rejectLocation')} />
+
+
+ );
+};
+
+export default ApproveLocationRadioButtons;
diff --git a/src/components/molecules/LocationSelect.tsx b/src/components/molecules/LocationSelect.tsx
index 871e5a6c..22a0eb0d 100644
--- a/src/components/molecules/LocationSelect.tsx
+++ b/src/components/molecules/LocationSelect.tsx
@@ -6,11 +6,12 @@ import Map from './map/Map';
interface ILocation {
onLocationChange: (location: IPoint) => void;
+ initialLocationGetter: (() => IPoint | null) | null;
}
-const LocationPicker: FC = ({ onLocationChange }) => {
- // const [position, setPosition] = useState(null);
- const [position, setPosition] = useState(null)
+const LocationPicker: FC = ({ onLocationChange, initialLocationGetter }) => {
+ const initialLocation = initialLocationGetter ? initialLocationGetter() : null;
+ const [position, setPosition] = useState(initialLocation);
console.log(position, 'before the click')
useMapEvents( {
@@ -27,12 +28,13 @@ const LocationPicker: FC = ({ onLocationChange }) => {
interface IProps {
onLocationChange: (location: IPoint) => void;
+ initialLocationGetter?: () => IPoint | null;
}
-const LocationSelect: FC = ({ onLocationChange }) => {
+const LocationSelect: FC = ({ onLocationChange, initialLocationGetter = null }) => {
return (
);
};
diff --git a/src/components/molecules/MapDialog.tsx b/src/components/molecules/MapDialog.tsx
index e5ea59dd..7040c94f 100644
--- a/src/components/molecules/MapDialog.tsx
+++ b/src/components/molecules/MapDialog.tsx
@@ -1,14 +1,12 @@
-import { ChangeEvent, FC, useEffect, useState } from 'react';
+import { FC, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles';
import { Box } from '@material-ui/core';
import { Dialog , Typography } from 'components/atoms';
import { IPoint } from 'models/Point';
import { useStore } from 'store/storeConfig';
-import { fetchStreetsByCity } from 'services/getCitiesAndStreets.service';
import SearchCityAndStreetScreen from 'components/molecules/SearchCityAndStreetScreen';
import SearchSegmentScreen from 'components/molecules/SearchSegmentScreen';
-import { ICityOption, IStreetOption } from 'models/Map';
interface IProps {
section?: string;
@@ -70,9 +68,6 @@ const MapDialog: FC = ({
const classes = useStyles();
const { t } = useTranslation();
const [searchScreen, setSearchScreen] = useState<'segment' | 'cityAndStreet'>('segment');
- const [streetsOptions, setStreetsOptions] = useState>([]);
- const [cityValue, setCityValue] = useState({});
- const [streetValue, setStreetValue] = useState({});
const store = useStore();
useEffect(() => {
@@ -80,28 +75,6 @@ const MapDialog: FC = ({
store.fetchCitiesList();
}, [store]);
- async function setCityGetStreets(event: ChangeEvent<{}>, value?: ICityOption | null) {
- setStreetsOptions([]);
- setStreetValue({});
- if (value) {
- setCityValue({ yishuv_name: value.yishuv_name, yishuv_symbol: value.yishuv_symbol });
- const streetsData = await fetchStreetsByCity(value.yishuv_symbol);
- setStreetsOptions(streetsData);
- }
- }
-
- function setChosenStreet(event: ChangeEvent<{}>, value?:IStreetOption) {
- if (value) {
- setStreetValue(value);
- }
- }
-
- function streetCityResultsPage() {
- setCityValue({});
- setStreetValue({});
- onStreetAndCitySearch(cityValue.yishuv_name, streetValue.street_hebrew);
- }
-
// the code I deleted should be here...
// SearchCityAndStreetScreen()
@@ -123,8 +96,7 @@ const MapDialog: FC = ({
{searchScreen === 'segment' && }
- {searchScreen === 'cityAndStreet' && }
diff --git a/src/components/molecules/NewsFlashComp.tsx b/src/components/molecules/NewsFlashComp.tsx
new file mode 100644
index 00000000..2f1ff251
--- /dev/null
+++ b/src/components/molecules/NewsFlashComp.tsx
@@ -0,0 +1,85 @@
+import React, {FC, useState} from 'react';
+import { Link, Typography, Button } from 'components/atoms';
+import { Box, makeStyles } from '@material-ui/core';
+import { cherryJamColor, oceanBlueColor, silverSmokeColor } from 'style';
+import { useStore } from 'store/storeConfig';
+import RootStore from 'store/root.store';
+import { dateFormat } from 'utils/time.utils';
+import { useLocale } from 'hooks/date.hooks';
+import { ReactComponent as CheckCircleIcon } from 'assets/check_blue_24dp.svg';
+import { ReactComponent as CancelCircleIcon } from 'assets/cancel_red_24dp.svg';
+import { ReactComponent as CriticalIcon } from 'assets/critical.svg';
+import { useTranslation } from 'react-i18next';
+import LocationApprove from 'components/organisms/LocationApproveWindow';
+import {locationQualificationOptions} from 'components/organisms/LocationApproveWindow';
+import { INewsFlash } from 'models/NewFlash';
+
+const ICON_HEIGHT = 18
+
+interface IProps {
+ news: INewsFlash;
+}
+
+const useStyles = makeStyles({
+ activeNewsFlash: {
+ backgroundColor: silverSmokeColor,
+ },
+ icon: {
+ height: ICON_HEIGHT,
+ width: 18,
+ },
+});
+
+
+const NewsFlashComp: FC = ({ news }) => {
+ const store: RootStore = useStore();
+ const classes = useStyles();
+ const locale = useLocale();
+ const { userStore, newsFlashStore, settingsStore } = store;
+ const { t } = useTranslation();
+ const userAllowedChange = userStore.isUserAuthenticated && userStore.isAdmin;
+
+ function getVerificationIcon(verificationText: string) {
+ if (verificationText === locationQualificationOptions.REJECTED) {
+ return
+ } else if (verificationText === locationQualificationOptions.VERIFIED ||
+ verificationText === locationQualificationOptions.MANUAL) {
+ return
+ } else if (verificationText === locationQualificationOptions.NOT_VERIFIED) {
+ return
+ } else {
+ return
+ }
+ }
+
+ const [isOpen, setOpen] = useState(false);
+ const verificationIcon = getVerificationIcon(news.newsflash_location_qualification);
+ const criticalIcon = news.critical && ;
+ const className = news.id === newsFlashStore.activeNewsFlashId ? classes.activeNewsFlash : '';
+ const date = news.date == null ? '' : dateFormat(new Date(news.date.replace(/-/g, '/')), locale);
+ const handleLocationEditorOpen = () => setOpen(true);
+ const handleLocationEditorClose = () => setOpen(false);
+ const locationChangeButton = userAllowedChange &&
+
+ {t('changeLocationButton')}
+
+ return (
+
+
+
+
+
+ {date}, {news.display_source} {verificationIcon}{criticalIcon}
+
+
+ {locationChangeButton}
+
+ {news.title}
+
+
+
+ );
+}
+
+export default NewsFlashComp;
diff --git a/src/components/molecules/NewsFlashFilterPanel.tsx b/src/components/molecules/NewsFlashFilterPanel.tsx
index abc04c8c..c27c6c75 100644
--- a/src/components/molecules/NewsFlashFilterPanel.tsx
+++ b/src/components/molecules/NewsFlashFilterPanel.tsx
@@ -5,7 +5,7 @@ import { silverSmokeColor, oceanBlueColor } from 'style';
import ynetLogo from 'assets/ynet-website-logo.svg';
import wallaLogo from 'assets/walla-logo.svg';
import madaLogo from 'assets/mada-logo.svg';
-import criticalLogo from 'assets/critical.jpg';
+import criticalLogo from 'assets/critical.svg';
import { AnyWayButton } from 'components/atoms/AnyWayButton';
import RootStore from 'store/root.store';
import { useStore } from 'store/storeConfig';
diff --git a/src/components/molecules/SearchCityAndStreet.tsx b/src/components/molecules/SearchCityAndStreet.tsx
new file mode 100644
index 00000000..173452c6
--- /dev/null
+++ b/src/components/molecules/SearchCityAndStreet.tsx
@@ -0,0 +1,75 @@
+import {ChangeEvent, FC, useState} from "react";
+import {useTranslation} from "react-i18next";
+import {ICityOption, IStreetOption} from "models/Map";
+import {useStore} from "store/storeConfig";
+import {createStyles, makeStyles, Theme} from "@material-ui/core/styles";
+import {fetchStreetsByCity} from "services/getCitiesAndStreets.service";
+import {Box, TextField} from "@material-ui/core";
+import Autocomplete from "@material-ui/lab/Autocomplete";
+
+interface ISearchCityAndStreet{
+ onStreetAndCityChoice: (street: IStreetOption, city: ICityOption) => void;
+}
+
+const SearchCityAndStreet : FC = ({onStreetAndCityChoice}) => {
+ const { t } = useTranslation();
+ const [streetsOptions, setStreetsOptions] = useState>([]);
+ const [cityValue, setCityValue] = useState({});
+ const [streetValue, setStreetValue] = useState({});
+ const store = useStore();
+
+ const useStyles = makeStyles((theme: Theme) =>
+ createStyles({
+ inputSpace: {
+ marginTop: 20,
+ marginInlineEnd: 20,
+ },
+ }),
+ );
+
+ const classes = useStyles();
+
+ async function setCityGetStreets(event: ChangeEvent<{}>, value?: ICityOption | null) {
+ setStreetsOptions([]);
+ setStreetValue({});
+ if (value) {
+ setCityValue({ yishuv_name: value.yishuv_name, yishuv_symbol: value.yishuv_symbol });
+ const streetsData = await fetchStreetsByCity(value.yishuv_symbol);
+ setStreetsOptions(streetsData);
+ }
+ }
+
+ function setChosenStreet(event: ChangeEvent<{}>, value?:IStreetOption | null) {
+ if (value) {
+ setStreetValue(value);
+ onStreetAndCityChoice(value, cityValue);
+ }
+ }
+
+ return(
+
+ (option.yishuv_name ? option.yishuv_name : '')}
+ onChange={(event, value) => setCityGetStreets(event, value)}
+ value={{ yishuv_name: cityValue.yishuv_name, yishuv_symbol: cityValue.yishuv_symbol }}
+ style={{ minWidth: 300 }}
+ renderInput={(params) =>
+ }
+ />
+ (option.street_hebrew ? option.street_hebrew : '')}
+ style={{ minWidth: 300 }}
+ value={{ street: streetValue.street, street_hebrew: streetValue.street_hebrew }}
+ onChange={(event, value) => setChosenStreet(event, value)}
+ disabled={streetsOptions.length === 0}
+ renderInput={(params) =>
+ }
+ />
+ )
+}
+
+export default SearchCityAndStreet;
diff --git a/src/components/molecules/SearchCityAndStreetScreen.tsx b/src/components/molecules/SearchCityAndStreetScreen.tsx
index 6e2318e0..ae8e9620 100644
--- a/src/components/molecules/SearchCityAndStreetScreen.tsx
+++ b/src/components/molecules/SearchCityAndStreetScreen.tsx
@@ -1,73 +1,55 @@
-import { Box, DialogActions, TextField } from '@material-ui/core';
-import Autocomplete from '@material-ui/lab/Autocomplete';
+import { Box, DialogActions } from '@material-ui/core';
import { Button } from 'components/atoms';
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles';
-import { useStore } from 'store/storeConfig';
import { useTranslation } from 'react-i18next';
-import { ChangeEvent, FC } from 'react';
+import {FC, useState} from 'react';
import { ICityOption, IStreetOption } from 'models/Map';
+import SearchCityAndStreet from "./SearchCityAndStreet";
interface ISearchCityAndStreetScreen{
- streetsOptions:Array;
- streetValue:IStreetOption;
- setChosenStreet:Function;
- streetCityResultsPage:() => void;
+ onStreetAndCitySearch: (street?: string, city?: string) => void;
onClose:() => void;
- setCityGetStreets:(event : ChangeEvent<{}> ,value? : ICityOption | null) => void,
- cityValue:ICityOption,
}
-const SearchCityAndStreetScreen : FC = (
-{setCityGetStreets, cityValue, streetsOptions, streetValue,
-setChosenStreet, streetCityResultsPage, onClose}
-) => {
+
+const SearchCityAndStreetScreen : FC = ({onStreetAndCitySearch, onClose}) => {
const { t } = useTranslation();
-const useStyles = makeStyles((theme: Theme) =>
-createStyles({
- actions: {
- gap: theme.spacing(1),
- },
- inputSpace: {
- marginTop: 20,
- marginInlineEnd: 20,
- },
-}),
-);
+ const [cityValue, setCityValue] = useState({});
+ const [streetValue, setStreetValue] = useState({});
+ const useStyles = makeStyles((theme: Theme) =>
+ createStyles({
+ actions: {
+ gap: theme.spacing(1),
+ },
+ }),
+ );
const classes = useStyles();
- const store = useStore();
-return(<>
-
- (option.yishuv_name ? option.yishuv_name : '')}
- onChange={(event, value) => setCityGetStreets(event, value)}
- value={{ yishuv_name: cityValue.yishuv_name, yishuv_symbol: cityValue.yishuv_symbol }}
- style={{ minWidth: 300 }}
- renderInput={(params) => }
- />
- (option.street_hebrew ? option.street_hebrew : '')}
- style={{ minWidth: 300 }}
- value={{ street: streetValue.street, street_hebrew: streetValue.street_hebrew }}
- onChange={(event, value) => setChosenStreet(event, value)}
- disabled={streetsOptions.length === 0}
- renderInput={(params) => }
- />
-
-
-
- {t('mapDialog.searchButton')}
-
- {t('mapDialog.cancelButton')}
-
->)
+ function onStreetAndCityChoice(street: IStreetOption, city: ICityOption) {
+ setCityValue(city);
+ setStreetValue(street);
+ }
+
+ function streetCityResultsPage() {
+ setCityValue({});
+ setStreetValue({});
+ onStreetAndCitySearch(cityValue.yishuv_name, streetValue.street_hebrew);
+ }
+
+ return(<>
+
+
+
+
+
+ {t('mapDialog.searchButton')}
+
+ {t('mapDialog.cancelButton')}
+
+ >)
}
export default SearchCityAndStreetScreen;
diff --git a/src/components/organisms/LocationApproveWindow.tsx b/src/components/organisms/LocationApproveWindow.tsx
new file mode 100644
index 00000000..a211b46f
--- /dev/null
+++ b/src/components/organisms/LocationApproveWindow.tsx
@@ -0,0 +1,202 @@
+import React, {FC, useCallback, useState} from 'react';
+import DialogWithHeader from '../molecules/DialogWithHeader';
+import {Box, makeStyles } from '@material-ui/core';
+import { Button, Typography } from 'components/atoms';
+import { useTranslation } from 'react-i18next';
+import { silverSmokeColor } from 'style';
+import { INewsFlash } from "models/NewFlash";
+import { useStore } from "store/storeConfig";
+import {IPoint} from "models/Point";
+import {IGpsData, IStreetData} from "models/WidgetData";
+import LocationSelect from "../molecules/LocationSelect";
+import SearchCityAndStreet from "../molecules/SearchCityAndStreet";
+import {ICityOption, IStreetOption} from "models/Map";
+import ApproveLocationRadioButtons from "../molecules/ApproveLocationRadioButtons";
+import { updateNews } from "services/news.data.service";
+
+const APPROVE = "approve";
+
+export enum locationQualificationOptions {
+ VERIFIED = "verified",
+ NOT_VERIFIED = "not_verified",
+ REJECTED = "rejected",
+ MANUAL = "manual",
+}
+
+interface IProps {
+ isOpen: boolean;
+ onClose: () => void;
+ news: INewsFlash;
+ newFlashTitle: string;
+}
+
+const useStyles = makeStyles({
+ newsFlashBox: {
+ display: 'flex',
+ backgroundColor: silverSmokeColor
+ },
+ mainWindow: {
+ display: "flex",
+ width: 1000,
+ height: 700,
+ flexBasis: 200,
+ minWidth: 200,
+ alignContent: 'space-around',
+ flexDirection: 'column'
+ },
+ block: {
+ display: "flex",
+ alignContent: 'space-around',
+ flexDirection: 'column',
+ },
+});
+
+const LocationApprove: FC = ({ isOpen, onClose, news, newFlashTitle }) => {
+ const { t } = useTranslation();
+ const classes = useStyles();
+ const store = useStore();
+ const { userStore } = store;
+ const [shouldApprove, setApproveStatus] = useState(true);
+ const [locationChanged, setLocationChanged] = useState(false);
+ const [newStreetLoc, setNewStreetLoc] = useState(null);
+ const [newGpsLoc, setNewGpsLoc] = useState(null);
+ const [locationToDisplay, setLocationToDisplay] = useState(news.location);
+ // Unauthorized user shouldn't be able to open the window in the first place
+ const userInfo = userStore.userInfo && userStore.userInfo.data && userStore.userInfo.data.firstName ?
+ userStore.userInfo.data.firstName.concat(userStore.userInfo.data.lastName) : null;
+
+ function handleApproveButton () {
+ if (shouldApprove && locationChanged) {
+ if (newStreetLoc) {
+ updateNews(news.id, locationQualificationOptions.MANUAL, newStreetLoc, null);
+ } else {
+ updateNews(news.id, locationQualificationOptions.MANUAL, null, newGpsLoc);
+ }
+ } else if (shouldApprove) {
+ updateNews(news.id, locationQualificationOptions.VERIFIED, null, null);
+ } else {
+ updateNews(news.id, locationQualificationOptions.REJECTED, null, null);
+ }
+ onCloseInitValues();
+ window.location.reload();
+ }
+
+ const handleCloseButton = () => onCloseInitValues();
+
+ const handleApproveStatusChange = (event: React.ChangeEvent) => {
+ if ((event.target as HTMLInputElement).value === APPROVE) {
+ setApproveStatus(true);
+ } else {
+ setLocationToDisplay(news.location);
+ setApproveStatus(false);
+ }
+ };
+
+ const onMapLocationChange = useCallback(
+ (location: IPoint) => {
+ setLocationChanged(true);
+ store.fetchGpsLocation(location);
+ if (store.gpsLocationData) {
+ setNewGpsLoc(store.gpsLocationData);
+ setLocationToDisplay(t('mapDialog.road') + " " + store.gpsLocationData.road1 + " - " +
+ store.gpsLocationData.road_segment_name);
+ }
+ },
+ [t, store],
+ );
+
+ const newsGetInitialLocation = useCallback(() => (
+ {longitude: news.lon, latitude: news.lat}),
+ [news.lat, news.lon]
+ );
+
+ const onStreetAndCityChoice = (street: IStreetOption, city: ICityOption) => {
+ setLocationChanged(true);
+ setLocationToDisplay(t('mapDialog.street') + " " + street.street_hebrew + " " +
+ t('textView.on') + city.yishuv_name);
+ setNewStreetLoc({street, city});
+ }
+
+ const onCloseInitValues = () => {
+ setApproveStatus(true);
+ setLocationChanged(false);
+ setLocationToDisplay(news.location);
+ onClose();
+ }
+
+ return (
+
+
+ {/*The newsflash*/}
+
+ {t('LocationApprove.newsFlash')}:
+
+
+ {newFlashTitle}
+
+
+ {news.title}
+
+ {news.description}
+
+
+
+ {/*Display map and search to choose location*/}
+
+ {t('LocationApprove.accident')}:
+ ({t('LocationApprove.changeAllowed')})
+
+
+
+
+
+
+
+
+ {/*Display user name */}
+
+ {t('LocationApprove.updater')}:
+ {userInfo}
+
+ {/*Status chooser*/}
+
+
+ {t('LocationApprove.status')}:
+ ({t('LocationApprove.pleaseMark')})
+
+
+
+
+
+
+
+
+ {/*Segment*/}
+
+ {t('LocationApprove.segment')}:
+
+ {locationToDisplay}
+
+
+ {/*Buttons*/}
+
+
+ {t('LocationApprove.cancelButton')}
+
+
+ {t('LocationApprove.approveButton')}
+
+
+
+
+
+ );
+ };
+
+export default LocationApprove;
diff --git a/src/components/organisms/News.tsx b/src/components/organisms/News.tsx
index 0325e851..5fb9de73 100644
--- a/src/components/organisms/News.tsx
+++ b/src/components/organisms/News.tsx
@@ -1,34 +1,29 @@
-import { FC } from 'react';
-import { Link, Typography } from 'components/atoms';
+import React, { FC } from 'react';
+import { Typography } from 'components/atoms';
import { Box, makeStyles } from '@material-ui/core';
-import { silverSmokeColor } from 'style';
import { useStore } from 'store/storeConfig';
import { useParams } from 'react-router-dom';
import RootStore from 'store/root.store';
import { observer } from 'mobx-react-lite';
-import { dateFormat } from 'utils/time.utils';
-import { useLocale } from 'hooks/date.hooks';
import LocationSearchIndicator from 'components/molecules/LocationSearchIndicator';
import { IRouteProps } from 'models/Route';
-import CriticalIcon from 'assets/critical.jpg';
+import NewsFlashComp from "components/molecules/NewsFlashComp";
+
const useStyles = makeStyles({
container: {},
newsFeed: {
overflow: 'auto',
},
- activeNewsFlash: {
- backgroundColor: silverSmokeColor,
- },
});
-//
+
const News: FC = () => {
const store: RootStore = useStore();
const classes = useStyles();
- const locale = useLocale();
const { gpsId, street, city } = useParams();
- const { newsFlashStore, settingsStore } = store;
+ const { newsFlashStore } = store;
+
return (
@@ -36,25 +31,9 @@ const News: FC = () => {
{gpsId && }
{street && city && }
{newsFlashStore.newsFlashCollection.length > 0 ? (
- newsFlashStore.newsFlashCollection.map((news) => {
- const className = news.id === newsFlashStore.activeNewsFlashId ? classes.activeNewsFlash : '';
- const date = news.date == null ? '' : dateFormat(new Date(news.date.replace(/-/g, '/')), locale);
- return (
-
-
-
-
-
- {date}, {news.display_source}
-
-
- {news.critical && }
-
- {news.title}
-
-
- );
- })
+ newsFlashStore.newsFlashCollection.map((news) =>
+
+ )
) : (
לא נמצאו תוצאות מהמקור המבוקש
diff --git a/src/const/generalConst.ts b/src/const/generalConst.ts
index 8bc0eb3e..5f9121f9 100644
--- a/src/const/generalConst.ts
+++ b/src/const/generalConst.ts
@@ -23,7 +23,8 @@ export const REMOVE_USER_FROM_ORG_URL = `${authServerUrl}/user/remove_user_from_
AUTH_LOGIN_GOOGLE_URL.searchParams.append('redirect_url', `${window.location.origin}${REDIRECT_ROUTE!}`);
//function return api key depends on the env it running on
-export const mapApiKey = process.env.REACT_APP_GOOGLE_MAP_KEY ? process.env.REACT_APP_GOOGLE_MAP_KEY : '';
+// export const mapApiKey = process.env.REACT_APP_GOOGLE_MAP_KEY ? process.env.REACT_APP_GOOGLE_MAP_KEY : '';
+export const mapApiKey = 'AIzaSyCfluirCgaQ769osh7560kST3Yo0eQIqg8';
export const showDemoCards = process.env.REACT_APP_SHOW_DEMO_CARDS === 'true';
diff --git a/src/models/NewFlash.ts b/src/models/NewFlash.ts
index 2a926086..85b31486 100644
--- a/src/models/NewFlash.ts
+++ b/src/models/NewFlash.ts
@@ -10,6 +10,7 @@ export interface INewsFlash {
link: string;
lon: number;
display_source: string;
+ newsflash_location_qualification: string;
location: string;
title: string;
source: string;
diff --git a/src/models/WidgetData.ts b/src/models/WidgetData.ts
index 15e7df39..2f2b119d 100644
--- a/src/models/WidgetData.ts
+++ b/src/models/WidgetData.ts
@@ -1,6 +1,7 @@
import { LabelsMap, MultiSeriesDataItems, SeriesDataItem } from './MultiSeriesData';
import { IPoint, IPointAccident } from './Point';
import { IWidgetDataType } from './WidgetDataType';
+import {ICityOption, IStreetOption} from "./Map";
export enum Resolution {
STREET = "STREET",
@@ -19,6 +20,10 @@ export interface IGpsData {
road_segment_id: number;
resolution: string;
}
+export interface IStreetData {
+ street: IStreetOption;
+ city: ICityOption;
+}
export interface IWidgetDataBase {
text: {
title?: string;
diff --git a/src/services/news.data.service.ts b/src/services/news.data.service.ts
index b5353895..12613a93 100644
--- a/src/services/news.data.service.ts
+++ b/src/services/news.data.service.ts
@@ -1,5 +1,6 @@
import axios from 'axios';
import { INewsFlash } from 'models/NewFlash';
+import { IGpsData, IStreetData } from "models/WidgetData";
const errorNews: INewsFlash = {
lat: -1,
@@ -13,6 +14,7 @@ const errorNews: INewsFlash = {
link: '',
description: '',
display_source: '',
+ newsflash_location_qualification : '',
location: '',
};
@@ -55,3 +57,21 @@ function onErrorFetchNewsFlash() {
errorArr.push(errorNews);
return errorArr;
}
+
+export function updateNews(newsId: number, newLocationQualification: any,
+ streetLocation: IStreetData | null, gpsLocation: IGpsData | null) {
+ const data = [];
+ data.push(`newsflash_location_qualification=${newLocationQualification}`)
+ if (gpsLocation) {
+ data.push(`road_segment_name=${gpsLocation.road_segment_name}`)
+ // data.push(`road1=${gpsLocation.road1}`) TODO: uncomment when option added
+ } else if (streetLocation) {
+ data.push(`yishuv_name=${streetLocation.street}`)
+ data.push(`street1_hebrew=${streetLocation.city}`)
+ }
+ const url = `${NEWS_FLASH_API}?${newsId}`;
+ axios
+ .put(url)
+ .then((res) => res.data)
+ .catch(onErrorFetchNewsFlash)
+}
From 63826f0b07a9d3e59bfdd74a969a0799da20475a Mon Sep 17 00:00:00 2001
From: EyalIlan <55767736+EyalIlan@users.noreply.github.com>
Date: Thu, 13 Jul 2023 18:06:24 +0300
Subject: [PATCH 14/33] Feature add transcrption 4 widgets 957 (#968)
* transaction dialog box
* show transaction icon only widgets that has transaction
* add copy image to transaction box
---
src/assets/copyImageGrey.jpeg | Bin 0 -> 1299 bytes
src/assets/copyImageWhite.jpeg | Bin 0 -> 1294 bytes
src/components/molecules/card/AnyWayCard.tsx | 14 +++---
src/components/organisms/CardEditorDialog.tsx | 1 +
src/components/organisms/TextBox.tsx | 41 +++++++++++++-----
src/components/organisms/WidgetsTemplate.tsx | 2 +-
6 files changed, 38 insertions(+), 20 deletions(-)
create mode 100644 src/assets/copyImageGrey.jpeg
create mode 100644 src/assets/copyImageWhite.jpeg
diff --git a/src/assets/copyImageGrey.jpeg b/src/assets/copyImageGrey.jpeg
new file mode 100644
index 0000000000000000000000000000000000000000..a6f41ce0a7764b2156c81f1be0bffbe6fd3b927c
GIT binary patch
literal 1299
zcmex=+
z$QDV5ur)yJBnaCE#4ax>C;_So0I`cgf}DZu6d+q89f_TU#7-_K0;%r-s5rZ)ISRxP=f?
zS-`-+-@?GK?L0yZ5hewRMTubJSb!u`S{ehxr{xR`ypaqH!WS4AxT3*wKmv!`6o67P
zKzHQ>VLC$&Ln?y;gC|2CLo$ONkY&VRz+lK=_Ww46GXpad2!KdtAYfr*0Rav+HdZ!H
z4lXWE4o*%k9)2D!Za!{KPF_J?K7IiKK>;ovAz>i_VIW%oWC$ZjCo>BNP@@1hCpS=(
zMDYIrgCGZkI)f53qY?v?AS1INMNo|d=>~}kqF4kL
zy~V)8%m{Q3vmk>#L;3dH)sn|%Cq?|7?5lcv!IPg$AKX$nzr$$x%(fP{D(`dOl3%Ye
zIdmv!osj1%R~(at|Q<)C3R97x|{Zusm^7DI>8y*LxSS^<=JI|XP)vxNMvtW|{
zlF6=2pZD?GzF59b_&-C^j%(Rbb$=v6*UKI-l}pJy7rEig%$wW8m0Utv4NiZ185s0x
zLjMwJult@s4S}*&r7u=iM!kK1O}U|?
zKQ)AB*;i@R3ug~!$*`$xPdcx6<7~UsWW`qF$DVU(4~EwrCsTM^WzPwTcYbsS1Ic)_`WnVRiXK(K*oYurOW2$=Ipr@lY3;!
zS}vJZ=6f8rkEZb^T+qD`yV+9QSNK|t+~Gb?uaNH0``k^x9_jaS1-wXDnW4Vo!>+!H
zCl_5=l~10o|Ig6jtMSjZ^FM>B|I2qLKUZI?PrI`B@~hWX&Bo%z+cri#h`!8qk@tcl
c-#1Q9PlbjGPKF7b&v$icNUzdZ)cpS@06+k2djJ3c
literal 0
HcmV?d00001
diff --git a/src/assets/copyImageWhite.jpeg b/src/assets/copyImageWhite.jpeg
new file mode 100644
index 0000000000000000000000000000000000000000..4c38615f74c1f775b1720f4cd8364fc9a6763b5b
GIT binary patch
literal 1294
zcmex=+
z$QDV5ur)yJBnaCE#4ax>C;_So0I`cgf}DZu6d+q89f_TU#7-_K0;%r-s5rZ)ISRxP=f?
zS-`-+-@?GK?L0yZ5hewRMTubJSb!u`S{ehxr{xR`ypaqH!WS4AxT3*wKmv!`6o67P
zKzHQ>VLC$&Ln?y;gC|2CLo$ONkY&VRz+lK=_Ww46GXpad2!KdtAYfr*0Rav+HdZ!H
z4lXWE4o*%k9)2D!Za!{KPF_J?K7IiKK>;ovAz>i_VIW%oWC$ZjCo>BNP@@1hCpS=(
zMDYIrgCGZkI)f53qY?v?AS1INbw&A&k$R#@~GDBu83sUF^e^xms<~=a#=0BDC5(nsmvR=wVyJ)F@MJJwQZkKxxH@g
z;;41o7EN8WF;7=Zc4fdUN0v&*hHDy1`}^lrr5)O~OiebpZ@0(fsB4RN26bzwOn#_x
zkYP=s@_RM;FWtW14)=4h3(ZQ6w77O`?~<3olfT@y`?CCM)_sBmI}fXw3JU|Opdj0VUCxyTp_>m+VQz-?|)e&?LU{@UB1Iq{-)aA6F!?#
zulnydtXp1mRVuD@b+PK5FIur{{@mF$GuHRpJ?@BHu2&9Tp6Um8u&-fT^SFQW>G(67
z>@RdE-#Rj7#_}8AzO>wS-TriCP|vRBTT_=#Y2tt4*u<21ZC35pO`kIhw+jVr(a00w
z&rtZ*5n;^6bd@#g(~MP#Hm8#>oFc<$m*y!U9r
Zlt~=y2@^OO=KfY_V%*ilp (options?.size ? options.size : DEFAULTE_SIZE);
@@ -79,7 +79,7 @@ const AnyWayCard: FC = ({
information,
organizationData,
subtitle,
- BoxText
+ transcription
}) => {
const [element, setElement] = useState({});
const [isOpen, setOpen] = useState(false);
@@ -107,7 +107,7 @@ const AnyWayCard: FC = ({
switch(widgateOpen){
case 'TextBox':
- Widget =
+ Widget =
break
case 'CardEditor':
Widget =
@@ -130,12 +130,12 @@ const AnyWayCard: FC = ({
)}
- {handleCardEditorOpen('TextBox')}}>
-
-
+ {transcription?(
+ {handleCardEditorOpen('TextBox')}}>
+
+ ):null}
>
);
-
const refFn = (element: HTMLDivElement) => {
setElement(element);
if (getCardRef) {
diff --git a/src/components/organisms/CardEditorDialog.tsx b/src/components/organisms/CardEditorDialog.tsx
index 5382086d..2a06314d 100644
--- a/src/components/organisms/CardEditorDialog.tsx
+++ b/src/components/organisms/CardEditorDialog.tsx
@@ -8,6 +8,7 @@ import { MetaTag, ErrorBoundary, Typography, Button, Slider } from 'components/a
import widgetToImage from 'services/to-image.service';
import { useTranslation } from 'react-i18next';
import { blueVioletColor } from 'style';
+
import {initEditorBarOptions, barsWidgetsLabels, barsWidgetsTitle, NUM_OF_BARS} from 'utils/barChart.utils';
interface IProps {
diff --git a/src/components/organisms/TextBox.tsx b/src/components/organisms/TextBox.tsx
index e74ec544..be8d0e09 100644
--- a/src/components/organisms/TextBox.tsx
+++ b/src/components/organisms/TextBox.tsx
@@ -1,12 +1,13 @@
-import React from 'react'
+import React, { useState } from 'react'
import DialogWithHeader from '../molecules/DialogWithHeader';
import { AnyWayButton } from 'components/atoms/AnyWayButton';
import { Box, makeStyles} from '@material-ui/core'
+import CopyImageWhite from 'assets/copyImageWhite.jpeg';
+import CopyImageGrey from 'assets/copyImageGrey.jpeg';
import { useTranslation } from 'react-i18next';
import { Typography } from 'components/atoms';
import { transparent } from 'style';
-
interface IProps {
isOpen: boolean;
onClose: () => void;
@@ -15,9 +16,6 @@ interface IProps {
}
const TextBox: React.FC = ({ isOpen,text,onClose}) => {
- console.log('transaction ',text);
-
-
const useStyles = makeStyles((theme) => ({
text: {
position: 'relative', // for meta tags
@@ -40,19 +38,33 @@ const TextBox: React.FC = ({ isOpen,text,onClose}) => {
backgroundColor: transparent,
},
},
- img:{
- height:'100px',
- width:'100px'
- }
-
+ copyImg:{
+ height:'70px',
+ width:'70px',
+ },
+ copyMessage:{
+ color:'blue'
+ }
}));
const { t } = useTranslation();
+
+ const [copyToClickBoard,SetCopyToClickBoard] = useState(false)
+ const [copyMessage,SetCopyMessage] = useState('')
+
const onCloseInitValues = () => {
onClose();
+ SetCopyMessage('')
+ SetCopyToClickBoard(false)
}
+ const copyHandler = () =>{
+ navigator.clipboard.writeText(text?text:'')
+ SetCopyToClickBoard(true)
+ SetCopyMessage('הטקסט העותק ללוח')
+ }
+
const classes = useStyles();
return (
@@ -64,8 +76,13 @@ const TextBox: React.FC = ({ isOpen,text,onClose}) => {
- {navigator.clipboard.writeText(text?text:'asdsadasd')}} className={classes.button} >
-
+
+
+
+
+ {copyMessage}
+
+
diff --git a/src/components/organisms/WidgetsTemplate.tsx b/src/components/organisms/WidgetsTemplate.tsx
index 479dabbc..9dd4b9cb 100644
--- a/src/components/organisms/WidgetsTemplate.tsx
+++ b/src/components/organisms/WidgetsTemplate.tsx
@@ -40,7 +40,7 @@ const WidgetsTemplate: FC = () => {
Date: Wed, 2 Aug 2023 19:49:51 +0300
Subject: [PATCH 15/33] add widget vision_10_30_90 (#972)
---
src/assets/vision_10_30_90.png | Bin 0 -> 106504 bytes
src/components/molecules/ImageView.tsx | 11 ++++++-----
.../molecules/widgets/WidgetWrapper.tsx | 9 ++++++++-
src/models/WidgetName.ts | 1 +
4 files changed, 15 insertions(+), 6 deletions(-)
create mode 100644 src/assets/vision_10_30_90.png
diff --git a/src/assets/vision_10_30_90.png b/src/assets/vision_10_30_90.png
new file mode 100644
index 0000000000000000000000000000000000000000..c0a1a3ab88d0c5dbcae821f7a360f57d532ebe0e
GIT binary patch
literal 106504
zcmeFYWl&sA_qU6?ySuv+U~qR$a00mQ*}PP?}zi@bk&~OGreI?cdzcX*44iqtD~iijX{9{2M33(s-mC=2M50bJG#(N
zVBZ9GH7&y4;63z|<>2b3sg7YEknCkOW#Qnyf-oPgkYS(ET~&-d;NVE{{~quVmS56v
za4%)53bF=3i?b(GOLJqd-?)@ybXb#peOUTz^y8Ta1vGMbMOe&{smV$ds%WZP$td)A
z1Q0mE!Rw-1@s`D$&mV|QQ=N@loZ3}04qe*ETbztjKW{bn+?XDn)s&oanwmFs7i9nR
z_c|AQIBWRrx3uQ98j6T|uu!G%zB_9bo$p!+&23Ooe+RwH-G;iiyP3-62fYP
z3oD@2f&ViVAO$jN>h$w-m*cZD@bmNYWp%XjJ7Ab5oOV484Na`;!5IGib%iuH?aSS$
z?Qk6N?rU7o&?Qn1T)w3w06<_hnnVrVy6rK99k=81xRMbF*uhtqZB+S|g#XyAGQ-(g
zv-SXf^y;h^$dZzh
zB)Dz_J^-NTaS0~>r=D>csw>-rXS)Pmd?h8NgUM{cjHo-G%k}Xz*29&r)&j3yky&6v
zK7anKnM5PWaWqqa`y~zw3rhoNFO)0kzcfNt5x%=?<>2hBnZ*k65J+Cuuh25?W}*1T
zWO0%apg55Sppg#R2=h-8pr<*ZQ2F!neDShH#D;jaN80BJ_~57aXCJ}Bi03?^c91Fa7JGpF;!E|qlr5_F$d3!btc?+aeq
z1K(W{N?nHHj`?r>qS4m_BCy3&+BbU~X)z|>_P#tp3tsLE_=mp+K6u~HMoZbu$TB5m
z2?_{s(d;SeKEg)7=^^OlHh6pMsUrAK#qXd!)1CldxfvD=A__?SbxCa=LzIrLMpprx
z)vGd01DBuT7qVB1-DALH6fmc?Z(ZjcG9>Es02R5%WwYb5DrD&8Y5Qe!>z85hjUoRb
zCLIU#k8<#}vR&INouG{gK|BzrHdtU8sD1tP_=FmKiJE~M6rDw%USqXCk_hd`4Vuk&
zbJN`(k`FK&T?qvg+oly1(E4vPf&cFqyDt+iWxeq$Awb(0(2NHK{tAWnD?zBQ8A
z1FY{)jr@`Y$MR3fl5TEpys7v1H!p%(yFs1=ZPB+^K?x0&U*q_H)4p8M@{5hQ9{TJZ
z1g)Wjc6D?x;37SjZ>3b#G?Rij|7T=~bXpu79Li^PtBvOH-db4|v3FPG`$1Haw{>cb
zo`7D3b#>DKMGC;1=2Hs=_+9E^BRak1KrE|5I$duzLog!7^{Djo*IMJokr+JWsMLtN
zW0x)h9StDHko=!KdwB1QEoTQ;2(i1X%$0a#Bm?MnVXyxw8PyF>$Bs?6iyayrtzZWH
zh{qWca4DcddEf8o$;QLe^5~HlAR$ACCwv$+;AH_g?0Z0)6G~dSWPy*(fvjJQ^kr2-2dzpO3ykXR6_YH1}6M<1Oe
zgTXeoeO`Wi6ciL^;+uoO%VbP16>|g#JSh2A9@qs6$qhQ>e9JG!%(K<&@QtNr`Q~(a
z^kh1HHBDQ}!F{@WY<)3-AOZ5%V46EhgQ!wcgS*t~l)q_{ignY}IiYXgPy5uKRkEH}
zoKc&BFqY}n0eUC(U0s0h#y@ILKyy<4$Uor=V-A9OxyeQyB2H
z@4UN&P?=evCu1FkWQJBubbG=pv3kiGC9z!v?T<#Wo+2>e0D|&MCUU>tR9QBBwLhU{
zC^1uwuK9=-%I{pKf26w)w`0}$C^wIj2J74wvSqJcLGSp?;||ajIPcMw*LLJanKtmc
z;d(z-X@YmHn;IDfO_Fpd+=Jm)McBy
z8dqo|=r2ytu`_x}<|^n)t5aM?R$HqOkVV3c`zo)(IH$mX7J5fN^&<+!Qx&QeRI;H{
ze7@<~Dt|pUE~$ayZa$h2EUs7K2)2m02)yt|?}R7Etmvvj1v`1ly=Iv8KK?MYFDpCh
z4@t0Ge%viNMBgz3ad?n2_24Z-(Miw?)fnn=YK{#wiOX|>u4y>
zZ4=FZB$xOux>qcfEE~<%pL(uc$R>aKw>|pff9prU;db4dOLkgz}4$Pd#gNJ
zPj9qFd!^jD#s6F!<;-AR|MlzKNZGicS4O3#uLkx%f#%s6zIOezoKF^Km~8?+bKjH3
zq}#3XE*c3l(TxRxl|Y!{@$BM=*OqoGAEe;AP1Qh`p^M^@#usIn<|l$TY~I2aXN{Qj
zfNy0O?QW7mC_J{1QsViTR)W`H-~dlh*A`nA{OJh)eV(eLA)*CeT)xllar?Ldjv<4Q
zN|?Bh7o|C>hIm_&ZfNWGJ|^b*L_?`n1*);AJ0J}s+Me?05TXDJ=o*EuQ=+2<++;o#
zJ}hxS1Bnxep;gvG+AB)pce(7#TLw_#W*j?yt}9z@VbRye~Vz@qP39G6)ZA0k4A9*$VD=1^;`>LqQ2!+yI)
zrlkY#0`Vc_pySRRglatumiAKrM3~tBE`op-J}ils5LERaFDgkE?he6ch)Hq`ZD%mb
z;FJkqV;T`6)LbiCpJPveKp>YN-f1Y+Pp&A^3-axi-5jdKAF@tBWecv9L4?9}Sn
zBml$^dT}up49KTCoq2gb_Lm<<0o2y9Du!
zOa#7}M_nF_ak|Z6ro5l@7chAJI$KnEZ6$(U3VW>PmunR+RP1j<_~FbX1ywnFNEvAs
z${caQ$^iCng5kP~L8|he$Dq;cU33w6K>suq9&LmSqwNM}aRlDJWGAdG9m_f-zzi+&
zS;f&*j2OHx0v+XoDZ@0wHb@ht|}7FsR%v
zsi5w{^?>*WdZ|6;9rK0&WM0r+mGsh~xbF~I(IjwMavz~#kVhTZv%sBpm}`Z630&<)
zH)hTo5+t@hP>W$TN`T)|-PF^byG{{Jz=JKvY0*_7=Do?(Pz7>9u{h(^Nn}es!sXbR
z8M=JQf0vzXL^-)^{#E2MdHJNeWzRnOP`*`%D4tipSCA(y4#`>UXIIP-efH%xX4)7q
zsBA}45xt%Fg1WH#Y_c9MdbiP{LJ*h=n_^znT&+9Kcod{Iw6r{Px=+n78cx~HDj94i
z@xG+`q~H*JvoUYQN!S)Bin1rrbRRe^ejNMw$YpG|q}P*72d~GNtW3n{Amg@|$LF1k
z26I98OgLNd(ERG(#b$rx8(}m
zq<;R$1Z5!iVYn=gtTW}nE5JP~Ez&cKMZ!u|0<*sv`M)dDWa!?IM2Q48u4Thb
z2%BXLA}(B*8x1Z-lyObMQ+@ej;)_fl5N%^dBshUp&YcaTW8`j%T@#>kKG-=}&B`~J
z(Ogz~p+-jyOc+uXtziU?Fvo@i$w!B4Vi0hrx>08sIuflIc2xD1l1+=t6q7NoWWQh8
z#$<*!9GL?p*yItmRYecuG70jyh(P0L8T@Kns<<-6=SQ&F%Ycy&9fv?VYHLzkG&?S7
z_-QJo?K7=ltA5#Vrw*JppVZ7D-X+NjtUl?&7Kk~32B{$@EhJ4y`84iUVNhcmd(0;w;41Wv
zwPso2wzE(2%GG_~!UG+`DwQ|qGaP;AUx9eS!69!b00ETart@moUlr;MKw-Rsho8LP
z4+xy3{ui-;PN_A}tS1w%L^`TrnBzOmzc^#`24@6oQ>-SI#n=~i@&DypqHLm(gReDt
z<|n(m|7|ObpU}`WMzXFT{fFl8oBj`2`QNMHC)F{3hf0$B%8kK$h`}G#!$KgMx?Z$#
z^ak@E@31sDXw3sxC3QV3?;SxmdJM1ibvH&Ssbqgl3Uo^PUo_p|B+Rp%V&=D+lY`TKJ;#f-l2qbD>sHnq?MPZ}sUh82wH-
zyxdP?)n3ce4A>EmR?acHz#dVe4-J3z6=#1!}rt7n_mZ&nn
zM0c>%>P9OP2U}Ht+1MMnSKjvoK5+Ha)zw{oz}wy(jGn6A?)JZp*oM1c{zB!_PL?!m_@H@_VQrMA73B;WX7a-pip>VNxJ1)~M
zBrI$kRC3GT;&c5&SIl)MDZ0+*`NmLF9YH=It5Kq+|G}>sp8HL-U;}ApVU9!4}re-br<0{jD4hkYbcQ`P1A)7
zJ=i>-G@T!#zr?FOWhm#7zAnNY|C^ednuJau2J7?0?(9|6u{xUK97MK!s&t;WW2Jmh
zw3tQivKP3g(>kI16
z$+@WL`1)TYRG^58{p?Zjko)-1`_dV(M_3RO2?~DPCz1O76*T_xIP)?F!)`n^Z$5Wu
zkkNCTKfo^Yzkj|BcS;9?SJ*iK4=JF4A%yK07`f3-O--$ZR|+kZzU)IRC;A(Z>z~2d
zjtQ1dm5oMf2cGCd4|#))p}&6ds(*{ZrsU!oDN-TC4rzNO^7C&ye<{HuUPiSDjloJn9l5Dq``O`v~T18%Es6#b$KvY?U7&
zX?IoX&;Vu`4H!@^%*#4B8AhJJE#nPT6%Y{MVVuj8@L3Z)DDVi|kIfZPS!c-`D_}gS
z%)dYP>7`^8KFI&$DbVw7IBo*#-GMMK?~DzAL%EK+_yx$bl_Fy}x2V;*6JWi!+F%<$
zPIFvH;}E{!=IH2nw=nRRD07kYrv?*=$f18l;4+Cg1U>%%P40PxUQr?}Z~w}_T{-#-
zN+?wok=weuHad#$sNqq^$H(n-e|5!!JY?IWWd;*QWGV0r&Sl}}fbfZNC^KG}Gzh^j
z{j`svfdrygisQI7sVEwLFT1qQ{apTF#(e`Jj4<_Y71B?~S&9h_-^pP)$zJ|ns+D0^
zSCp(fV2J1-d*1`=-uUkLKA(AQGcfzbOCPF~C5-Ycgo^L^)7DKUe0
z*nj@f3B)bf_-pA8-qIN1&^SL=$EDh@_HDS#SZstu1a1VlhjJm;S5j1FCT*-H%7CK-
z6kFV5u`j0|?yf+=PBZx00ju~~v+|D{zkGskeUzX$braz2_SUwxl{#y1a&TSywL7lD
z4)|3*s}hpe^aBS6$C)_OPe^~+Xm>$K@kpn8$U?F`jI9MetZ$1bCOx(T@TF%MG7V4Y
z-3x!p0ZJ305ku5`aWR=4aKMo!#sv7~3_5`rkN_QRdV0F|W~lu$ETdZ9W8IwQ%f>pu
zXZ-Zw+lqM*+j0y^7TPx#pI!2mzLjmd8WC~EBlqalXN8lL?`eNtoe2_oV-M!`>VH6c
zOrj@nt~j9X9{vdKR_8pH$zUUdCh){i(2ONHN-q!&C0P`4&n4X@-T`?>#@_)OU|zxU
zD;fzeR=-@K&KMg22?)b=N*#FILvn)}>gs6?4FZji`2o=Jl`Ncr5iisuZUWx8oLBT0
z0|RpG+}w%CTnc;4I1#JtQZl4iZ`cq(be&4ki%FwM@NGb#C=JdV#sk#=z!5-9hT=U|
zSF~rE2nFKIWq_Ssd0C{Aoa=oknJ=n?$A$m*Z2MZX_bMCl$U(xhh3z1LK0TI1Htd*u
zpOk{X^SeAE_M5Pd{gj|;WRynF`|GQvD;P7hjzd63WRtITirFk9Rz$qtIV`cvdVO+|
z+~8`#>`fJ3rMCSFgH-CAGbL=XX+BCbK8n72TGu9R0*s{<6{a7N?!S{u?RQU&
zhmgus!IBMTnTT`hv2sqs6S6Rm&1O$ohA(EUy}&cL@PS268<3%#*wyg}`_&$>B8}1p
zw@{P~^)?8C$w=@qOJFzXUuDs>71`#o_alTo5Auka3;1q(=?$e;u
zD&Q5ZF-y4Phfc*;?XdiqBrB5#ca7y7b~+ZusDq`ym8daWK2Cc`ok%J$a(86BS8ksA
z<{;E>fNWQ6jeaDLQSBPH8*3<jF_bXep2^a~yqKGYi_VUE))
z7zMEPR;DYj(p@GU6u%Khxc&SwaDswGj^gK9EUS^dG0OlXos&C=OO>L?(K8MIY!Pmb
zVMFL0MOdRZJOp1+mQlIg+Dt)`4J}FN+xz!yh6qgGi3n|9Q5Ry3kvddWRiS@Dkr7J~
zq2RNq{UuUgOpiT}3eRUphK!MIuab5;j|`*-DErQ0lig5N%Fic}%1Fg5d(q0tC85!+
zDCDy!B&P1tbSx2W65@gxOXZ&VPjobrXADA>M;Z@Udp4S>O*3EFhRl03+NSg>z&s@u
z&K`^O0wOF!WJOdXxo4okDtiBAa_O__XY)%5TP+{!rf#cQsLPh(^3|d%b66e+U!Mx*
zMd0vMbUF<@_wbz
zq&**mh|@j^dPhjo3{Ylv8n2XE3EKqAX~+|%NB=CNOBW9;LyZ)=3~Hktj1oBr
zX~ogKq#Poa)(+YB746kuo?gkt@{p~^%2S9PYPOQWg|kj+LcNCDx-j4~ULRW7r#^t0
z0<+Uedc)|Cu)botx7TDTBkymY4A4mOz8{bodkDmCbT-NS)^Lpr^HT`El%R3()Iy5F
zLsHL;O>j(5g31<}^9b#vhP)=h&9`JMq!gMv8?C{2T4+eP=*Z^if5*;H$%fvw!`3gZ
zINV9y|L*m-JWTj`P4d@ha3I_;IrdqZ;(g0x28X>?1#HBRsY=rly47jy7&3#|xM7Mk
zFxz9@BN2_;H>OpMEG4TQ7mdze{J1kuavVNBtcX^L({GBjt6}Q69+hys8
z_#-LF4aRArRJ9irrB+#8iB+hV8fKp=!4)_VHI)qo5G!DF;g
z$WsETI3oHh<0EQ~h&WLkIx47QNQk-rCoDX!ZlQyCKN$OD_?S%XTaLLrH3-)v76l(u
z0BGMz9EWq5TU5&v$Yu{x650YZXs=#Q|FGe~l9=!7hORTu1%u+1}bSOI)yE
z*danCurpT24D}v=9rn)?D}oRl`WjzPo;S{m&-Sg}>Y>0jGpu>AfwAP5p
z@4%MitjI7sM59-$Kd0%EhNO%$BBf`{8<#Vw6~oMi21
z2nH&Y;JX=h@RN
zwT~G+=Gy~(ho=t5+0DBMy6vh!wx;)oiooKFd#+rE>#3?RxNQA{cb^!`iUH1>-^R@hWoaLsJ#pUd@^-Qt%`F
zKuAQ*06=2>RX~(4pRoJib?J-%aw=;A>(DaBSz#S|-j6Al0c5dAqW&IdnTI+t8^vOYHvQ`=k+zNJ-8ntCA%YERY%?aZBEQSZ1q-@-6g)_
zy4iy!&AV<|f@5n?L)_%<31}^Ry9o9I*)YySuQwjb1&&XOZIPh9Aao<3uTLZIC2h
zxA7b0=dt(CE9DwSP>CZaC`aVdnJ(nzlu<>VGJH2?p&H3t4}f=PFh7u7qeQ%N&lA!t
ztML#)!u&zueKEL#jD_A_XJW&VGMa^UO+{yV4Y5S~#U;)j#GWeOg_TO`N#j8O*@cU`
zWYBkQEFeJil`E3EuTr!l3C4e-FWKT#BCCXt*SZ98b)}?_ND;Uyw?7A
z3sfS6UaNljC{NYS?JJ8a{~$&!$S^xahc0Z_#SjH(hN)Ulh6>~aC{yzzio|8()lOhq
zb6eIUJ8W7bR{_-zKf`pG2X;*RW`VW5KA^n(l*kMcx6LRp6d0k0
zWiKUet!((dLx6OUq-%Zc0Hy9@U>Gu+F;rWePH8OPvk>km$C6%TUOjs!T}SGwVn8F>
zQk77>qu49H3r}=LOR3&vGPiD3!9BDqO=(^^yUpb_7CnUaelSgupYfDSv&8v|%i14I
zd5gCl5cZgc3jOZwvA4N^=^neQ@RUNrQaikC#qbxaPk?c~lqeO>Q&{IibLCRUm~TBc
zeVYvt%r7=@+poBgrVgZ71*cuhAL*~}#654uO4;o#6(nE#=}`H0*h*_)d0f%WH0f@Q
zN~TR26==UV_YF%#jU>pJ2}7Wl$3qhm2|0?J_mucHyHhOqOqFFIYrWI+1BVl>-JfQ+
zi@>2cp&djWgf|b{f>Wc>vww$r99M9F)IXaDVPea;e-);f4aEstj|sJRNPzY1y;eAb
zq>DQOMyM*~BMog^W{BMPz=K6{@+-@P*r?G5UtDawQ<0vD3^yT_EFs+}JXqS`UA1R^
z-pwY>0=%R?4Qf#Q34G1Qdw#UZb18Zsf_I5h0?PoQJbTeXaE{KaiSeG7R5QO^dI);GBx+s|S=x2#rNjYpKf}cs?J`?%CJrRbGg)M9
zaIxb%^<}_C?@N&518^5kxi7t&a=O2AKVQL1#npDeV~j5f&K4z1VyumBy3&R-zxz;jE@r5!=mIl#9s0DW2Pu(|7x@#YZ
zl8FSyE)FP5(!Be-V^2bNaZWZr(`8}sZSgIX$n#!fq_A$q7hzW#V%2jl(uazBs81!6
zUz1oYO_D(2tHphAM+}M_P%tA$4OBphR*<*I?f@xA7-Xe2@XSh
z2@iv-+dd_*{*mm#G84B$$XCBUGuWoYK5u2)5S#TXIQ;)wVZyeJHZeN*w^%EMsLPoc3r$k?fB2q1pDY^gdN@b|
zgW|AKhtS59WLi%7O7EDNzHAB&7T3hKN<#lpH@2Y^0=%_V90Ugf2%PG1Km99j6h=AZ
zYq{y#I!j+7W`>@>e|z>`-U}OTj#s!jmdm9|
z2wt|#y#6$<0HjB_H9e!Li(I}bxCFJiBFg-_K=+=*!xxDV!+VdkAZ3TWM+eyf)gXb&
z5*56ZcH}vI7uW}ltpNmS;|h?u{WZk^b0q|?snyz0K%&;G3a@h4tIbOH19b0Lgh(+y
zJ|;=YZuhG_W-ejI}FJe6-0|v1gD3gSLvyGjdy4{;3o1y4QD%IuW^lr6_sr1J%26k>!
zR?3=c+tKMw_aB$K#E+Qs>+6ncLNpl^UyL%Dl8G^Qw{hg<{5!X4SzC+Bto#+Hyj7
zo$yUq*I13UGPlg$CT9abZV9aBJB*TELE*5nUa7EAJMzMuUQu+JNa)rL0ezn!JPUv?
za-;9*v^7HR&?H_dV${?#Z`51@*QIk2PaZU3scLCvmJ&%dG6_qr%bARD5bwQCEvJ7i
zuf|kb-N3Z+@mS1TdIrVKMorBmLnOkC-Js~pT9YxwEj76D$fT?_m`-Erl}gR%Uf=k*
zjn{06lF_ehlB$pI!5GYgX3Tm-W@<*uNGE<~7H@Ji6l|GU1SvG~1(Gvm>{9gv5VKX~
z?F5+Zy?Sc7-}0{eERFLEKk|5ckH=7i>$VBKW#6QUj~_oNZ~fSJEwkT)sAtixi?NV3
zV<1mM4F-qdsELZHOpT=yF>Bk5cxtlA^BZH_XuFyp>e_M`Uue(U8-Aer(YSEUWt?tm
z2{ouuda+vchY4=Mb8VjH9|cP9uaG1PVlc3_CB)ZkU!I>%oSl-Lh}&$40fY)j#*u=W
z$N+A~W|PSFw5X=DA^N%Q2%*KYiqziz5JU}@-mB5xzs_C
zh*11=QodJwbQRj76Ti)G^o%;R1l-*rFJ$13#JC0DA#=LzS9T47*8!gaui{PJNx?#-MeS*Oa2~A
z4_wya*NBnM@nyk4RaN!1IzBQvnxNb(*+NDP+zY`!w})X=Xu)SR%nLuBkQkl2K|Zgn
zd=Ls!8ckr_S7TP9vun@HDU06wtNh97?buqgBQvA^DLP0logg2nVeeq5XLQj^h>o;s
z*FGR-i!_a&RpL))n(~$`pYNO}3_Pk^S%o@n_x#mC*LJR1JJ3&S34Z+Qc45J8YFISl
zWg+8v{pNk%o)-#KAun2h7_tmh;gUDRJjN&A>qcVLu5$Rm#KNj>V)E%^*le}Iw=q}D
z!)~u0>E6{hcH&zzOvmj3|M_mEAtuJ=_V#8SsAOy$X;b;mEW5PyQ-0MzWW^_y7~x78
zyC3#Z1Pq}rfK!P2vi$;PbMH-l7M_IFqRg^}QWQaR6c@OBYr?*qV`_4&TX%Te{)3(O
ztng?0-pZj4B-8aZ<`3E?EnLBm_~!i-g?U
zYAM~(`15YgbBva9%OAGAdr}hfdyK%sQXnqz+yBJtNEmU&eyBb!7cR{f`ucQTS;=}jFs?=s;T7c6<qw1TM7Kf-&?CE
zF=YrzsQfXkO+YuS+CV>bK|lkNyl{YZlhMdTs2DHM?9a+^gf1KGu{kE@8>!b>Gd&VZ
z{rGB~s*hcEjFn4W%0U9pap?qsGq}S(&y1;>wc^K}#Ou>n+=`O;pD#+&k5j9m8D$s(
zrs;2gpFCc+yA^xRtX+`*G5rKdkecuafQoKTPorVYr@We_lp|$yZ`6uysj50%<)A&q+FE!>`blKXq^es@8N3Q!d+xHxloEpLqZc)$L30_&?(nTONrGGK1=6Y
zd|>JUl8+gPSvBNp4hc0F80+nGGBax?)?=M|@%!T35Emd-plbGj$L8F~faBGj^RLU7
zGCnu%#$@f5GuWW43nP6d)vj-h)Tf!8RqO|Ie4YQ9^63)^5E)2h6jmhXi7`d
zl2vH%T6K3*fV`^fU5V3Xi~R4O5^SSMdEiFwqrmsE};uQx10r&
zCG9}K8<}Num@wVui%Ho{TDceb!snXkE4&5L?PIr)h{Tx1G_z)ow~6iUt4&o(ryssh
zy>d0u$`das-K1Y{xoCLEb!S|;Gqn1eEADGDohwzbHQ=_|SfSgpbf#1GhTgYb@q4UH
zu86AQA*PtHJWm26g^DBJS>cwhNeB1~XXf|s-%ebS+RFmXOg~(iDCi7GZb~*-+viPv
zbv5tPeb-2nn5?r|4@bC{MU?HNltHolVT_bGqx!ir1g~;VlIl}FO4X_fXW1!-t(R=dIJUS8^H5Db57fpXZfLMsLlakF
zsvZpqTQ`$^t^wc%yn_ehg
z+01Tnl}nPi!|aB{_+38~jYvOJgn)%{sN|PkCc)V!ncem_Aq%42EyU=7&JlhAf%2gh
zdq?Wy>blhqO^o?r;!O|_UaJ>%MX6dW1-9m>)==$1;nBxpQW9=l
z5Zs)=Zq7seAqLl%@flul>4AZ&`b_dePbx>yP}5%1cCZ#M5Q#Ni>0D{3#~M##hJ7D{=h0jZs`fnFAC_!dxdM
z={??ApqdMpgHcsnsvDZAb&M;c5JfIr`}sD}4U1uo{g`+oA}Y?>z}YxU9G!sH^!mC)
zLc$d=&y|oj(E;SwVTgEqetw>wR-sh|UFT6$Yhm-wQTk}{6IkNb&mviwT(aVzk|VOL
z;;%3kD@Xxg2@{ZgQ+x`VX>DP5d%a2!LnLhJBxyAy&zvY4;h?*oZ&I|wzR}IID8`!J`-fpv}G1gu(=_ikoiH|rAZay
z`I&Y}>f?G8AWy{lRLyHoyx{aT&K^1mIqZ(f>P7sDTxr8Xm3}y>fI@{Hw|zTiJ7GTI
zDgJPoZ))P3R771)xkNFUwl+2H@is5d;U`l`rxWj&@ASems#sUDi@QtAi4Xm5pkb?d
zr+;FE=^XPyclo;zj$Zg@3gP{Zxv_nI3~`LIMa$%`L9
zf2J@hCsp2d&F#fq{Go3fQQeW`S~vP^alOmZwMsW&^hp?~f#h{|lHEM>ut+wcw;xxA
zA#37;ob3wlpK#^=^{p(CBH@p`3{DvSY-N3e5B
zkIA5=N^3+lRxC)AiGE!@qhAF0ujNcTKc8CYzj1MwQ)v{c;lb{#|12RP@m5vDFtMdi
zrm}jCERA&;C8OBP!4J@{MQW1R;!LkUaV&++bsuYEBir3e^rW%0jj0AXm`y2JdZNVD
z@6%$CzmIt)XI@#n_eDn&(MSIsvMETean~f9RHZY@fD`KD_2*1%waxc*=sG$yKvB{R
z%#lXY@^gjx=|ojbq4+vRUR%2r_MFjh*BiqO-9!7}Xu?l?BQP)BVs0|s3enkENz0)V
z?kRdXSou7Xi|<6nszoiB^Ia=!rj2`ln82sM!fex;iTIr?;
zi56g3$Lv6iFYBS%Mk>kszt_x9z6!h{*Z9y_=*PAdF6^ssyxvr{H3nmZN2OhJGhcYHnhXT9|T%D*zv$GPdxjdUeW
z1@Pk%BFPn?F?>c+Mhh@mwsrqx@Wuc#oP^^q^}e!bzJTlo8@WNc*!C1mz+`OJ@#YOv
zMU*4XYb`SwxA(qKhnuQ`1^80Wu6rjkd9<2Fl^sRH{yKAir`##Kn3IPrg|M!JBU1K$
zEw?F;yHDr>HI@ONn`#G^JQy$76xYI172ExHPfMfkx8ooS+GO
z&W~r5Yj2FSoJrSg%zevh4F+S&{9W=<&99A{bRmFwJI#C{s#gJ%`KaG-hOr(lB@II!
ze6{7nnJUVwsfxmdZ0yxd{5p=AS>@|G7CfbW%Gt%=T5w0fT(dpR{zn;(R$zv8g7!
zH{AOT2@jepD+<4Mp+i2IhN7`J_XAlgJ^mmptVAP&t8e!%2CJ$_obf7dxso1l+&w&;
zdz1kwBa|a%*0v#>w_$q?M!0J~R)p5y13wPtOTumx%mEYXEd9PW>j`M5aJpYo7nCeq
zHXua_9xGxTt+k&7ob%DnJtEzk3S0StxE&0_-PT+31YVJ;q!OnT-TgTo%t)*(s2l|SEtXJ3eNWjQAVw;!?-fW7g5lqB=QMkT5p6-}AhUL6y
z9-n#+1q-bOj%b$zClWbRt?MEn^q`qGI$x->hT0yziTNIFz4$xoE5i4P(+@G_k=k~9UvtCy
z7@UrFJN(NrM{LKG`E(t-=2Be{9(EdH;nGaFcy}*=Cb?sK8BaExyA83oiE&rr1eAmo
zwYd%QVp)2#j$q0RQ6bz}CbmJG)u|+$Fn$Q%N?;B}t#EDpo{-?T?0*3dP50BterVfE$80TkIO20uc0|v2>J;tfjr;
zDQjZpSINq%j`T)GA-I4e!SXdO0d3>Hu?5joTAA^>jMcbF)pqB$U)Y<<$##*UiwsfE
z`XCnOiuLbAnFDnv$L01?g$^(ZidN^2HzLqH8}|Gxqoa%GqL0FnC2W3pm_F}bx0r8L
z~ti=#WxmJVpc#kmxLN
z>ck=>_tAIxac)+(Az)sn&HL{CtofA0hJT%X@@QpBqv80XU825J3REau;V>lDt@dht
zy=|K%m(QxK)bn#`WZLUV#?pYBAd(ls?BVn>Ow8CjpL}sQh#$}V>ygGWLlP9$UwBP{
zmBse@aIW8-;%nJ?76GMe-FC0&I6sLldtcftzjjI9%CA4wo0uc~34A!%MvMlnqCvB-9Nn>SW7qsx3XW$L5sb#rD
zy}_ZuPWb(e`*XjOHOtQ`8h6_rmIYms@o{#&HzpjJJjm+kq$S-7MHj!3B*@8{czM_}
zh&pTxUX`S4%T!*;wK%W4sLh8qho3I)57v0d^_eJxIS}fdPnRsi`WXh;zgmy-p%@7e
z9N^Lm57+sIGil}Hu&mJ)*V+O~4`SV{90dov6cH^*58d|+JT5mFFz@87x1R%B?1Uq!
zy9|_STNw>Vz(3WPiKdqU$B@xyVzHpdQfCKMQhou#gvIKkoN|lkRF~8HK41wK>8Frl
zuNYRduXS>%sd}GB8M2xwCS@&K1adwrq>D!P8oqwLF8<+YcoZ@Wv1!(PUTgabNsx49
z9G|c)tgYIv$0D<{oO1Kb>PJ3^J+xRoS*89U?$U6;wC_1_U-%$2J*GZ0#HR+!)nuMY
zaAlvBl%i}0qjU^E1aT!=`Hg!x4EvGm1giA_!|D#WO+Pqq5SI-4q1{-F*wC*{)^ep!
zF`c&9O_<=NZ%0P`#rF(4V#LJhYBA&03JU}YcwF#dp&=)fzpIjw-Z=}tA3Pr6wx3o@
zk{Y~&le08;s0J4J+O<1XSI>tP{9&rN4
zYI2$N7LXh199x_kRaK_PilkCg4X)V61=@%6Wk&`&OtEIEjf^eWVVX_%w4=U~;)$Hq
zT3`3`4c|_X1+Hjgn!WeghV2Mj!!B0iP8z!I*-~0{)QJe?b6bk+CTz`G3|Jat!EY}%
zd{Zf_Z_x3^#01foVtzC$R^3q^+qr7f!I>z0DnTU5eId(=686|V0avDpYo!G_jX+qS
z-LTsFW>Ocw+2M$(b{@LtSh8K*BfMWA#qUb`nxA3aYo7tv*+OU{{|nGSFTXomGBeeq
zSEp#xrs@eKyBN^-dV+Ou3SnSi$Og=fbW|vVZcw@;P$D_14A|Cgl^i`5nJ7X9@_3{o
zQ5Y-Lno3JcSBs1Bsw}Cg*(#Sh>AqNe&yM%wH8eIhN0tAZ#g1Ghx7g52Zcgwf%^x5hV
znQ`8kjTO0`3v2LIv93_y>fe1*ra3BKE0a@fDFlX3sVY#`TstEUEVkSr7aKNgFhxeb
zknI&KlV#`5-QgXsuE%8@!=S#tUP)OEkZ{9;pvxGUp*x)&t1@Kwp1mexJcS>8{hMaw
zG$WW)yQxLzLUj;guc@gYz$PQhMl|WO|Vl?00^`OEOo{Sg2_Cq<;01rcd;NiCB?Ue+D8)8l5?%lg3ceOTR6<7|1j|cafmmYbha@|HFS?ek^Wf=q%
z!phW4DP^fixEX~#XXJYAt4-Ryv#8IvcgX63V(Zn2Dns)elsGv1w|dhiHQdIB5fXv&
zX=rG$@@LrthEK42)6xU7)7;!F<>lo{u&Fky^zwDJ6G;{vIebWECD>P))1S;+58D~T
z5_E^sEefCjXTV&)AcH|BT~;sk^r~mNE+$XWHic)$xOD~N*5QoV_%e?E%^A<=pPZZ=
zJG8@%O@in%i-qX=RnCHChbBC1&KvIN2o3x=T^UU_o_Kb4mZYkohg_v9xw<7hw&%Ng
zxs8nzce#s}&wNAQ;|bOfmNzHYFn~@Mj3ZYQZdH_!E8fWQ6G8Wib@7D)5=E4_5a@H~
zT4HMsxgPy}u@Fs%6JWk$6r4YQ-Yi`Hj!$RwIlvyKl@(Ril^G>if>Q=tw$)m?
z^_k92X4sUT34nANyK-`62B~DO&X?1!tJ(g&o!QzFG*hh8dZwHxP>EFy0L7Ao09IaJY`$EB`
zBVJ$~5~b5!vk+#UHIW5{C1JS*UWro(OnBmO?gQazKh{NTYk;p&gyq4%H2WQO4HJ~1
zBMLrIh8*a?#{6JZ^Br`NUtZQAUXg&w>Si%Pnp~JVkeTs%XOjxL)7>N-S8jZ#Jd4*>
zNKb#b5k{E(rB)7e1I<$;UwilNxBR>Eh{_b})XOT?OJ}&O$+g2oGUBc$g1a~VnS}=L
zj}K8ycHQMGdYyH+bS*Q%(9Obk@`Rjm1gPs_iH~nSq3^nJ36_F(h0W~9%1UOlF%_P{
z@}QC+Sh}s!)q~v^+3%O9T)1ID=0ly?+SabdNpUc#Ld(sRW~d-APV({!1o;4qJ;7_H
zaPs10hFzMN%#?iDa)`haD=JwlmpY@K-Ss6gt{kQY?j2Y7cviLH*`jVjiwpeC^=-TA
z%!uVtN9fag=QV&xkIw1SXH@qDCn!bB!x^96m+jZLr)dmHvjN^-hzPNETPSV7DbW-M{1Hg>BRz1MXQx^N={
z-4N;rIoYfVA}7zr(oC?!GGw1rCc93bA9X99m3ji_Gov#kc`Q4AVo@AsvJIiIQHB^
zK;PrLh|jm4w^_4H`_9VF)4&c)K|^1z3Y6VZm{|FqU=4GW_2z#;SK
zqE@)AZ_CKC*?tESOrE+HK!bFRl21+&vR!4uJX$_g8IpIF*EnLp7#kl(;7ja}1p-E)
zDxes-#ie1wpYxeE;vOehCogn&7MBIPq)~`DR1aW>c27cW~Ia5pGB#zqm}=E(HVbNVTnV<$oe@;RZ&m
z81x?meRyO7R$l(?H%J=nGu#MVtEUL^F+^{Z7~DP84=F=qA^3T
zJL~FW_r@MJ#J(&T#$-r6o<9ATEj9Im%I}!U{3vparY2xJ+PFBq3lQ>rU_4g7QSWXB
zDW?swB*mSN>)Ic4A6U8*lqX5oXJYcg=e0>QPVSxTx17IVOS?FB(w26GOWo*6V_o!)
z?R7y}aXTOOJ$Tk5D9@l^g1=kaFG_Afv9(3Y(FNp-6NqZI?HHe&NR{xl7aD9B?N(rp?jvRVuPGKeI{mYgYj=3ltr{W=+4`*bBCRi8*j9r
zJh(HcfHmu(1
z@M#$tI-;RThDVxJU$d6`g3;74W1M)fu&xVZOU(B
zWntbX1~vi+4u2>vE|Fu$PE7F97Cw(`b2(yp7#Y|r7xw+1T-f#((pK|V(y{v^a&hmc
zr1SU>WpwbY=8>~mnPI7q&4Zgnye>Gjw|B_qEj2dtGrA^r0?BAVQ6f91&jv;r2*%vz
zHjN7fCkJd3SiXL}8Tbq@#Ooj?3}%`}NAR^tfv;GrXy
zzf3hA;`gSG23u;OUROqXwrt+KRW5|Hi5EJL5Np2%B)+$0tuz<^mh|SmPzG1ORQmH?
zES(vTVkLrFjALd+nG0cIW1%v%p{GgthK+KutJ~BN3h71#4ZJ}WWu^)&M@TVdWJ{b(h!d4z5ZKe16EE1C
zcY?xPVsHct`uhiM8AVD8J62uUfFS?b8aUsTNh&$ndD4h0COK&9BN(bDrKkY{RpGJck3d^MLlYi&9ovDXA&yVWedTg3l1Z!il`uDl;NJuNpYm{ICWBHYp6_S*anlRsqf*JZ4Zdx9D_BLAEq1`OSwzE)R
z2eI|**V}fTY&2mLDsvK-UzA|kG$>8=`HAE6d+5OpMz9JM#{T|3+e95JCMfuz0_gT*
zi^OE>7G^fzc;#@y1H_P=9*}JF+2E81yjWA5(Ey^~uT!vSyKHTxtW07H$=qOh6YGfe
z(>Cg$JXI+K<*DU}RY^JG;c7W%Yk9IQAXth@LRFWNZ1DXE$A*O-x+7TRgKj{DKg^96EB3n!!qV~&KusW
zUaZNA2G<*PE#jnluNfJte>gra%%=;?CJs*F8qdG`jdED7?X7HG#e^Z28x?2Ip0$&6
zAXs|EtY^u}Yg~V)s65$(ONbS{guEeV$*HnoLse`W*ZC+%jq?U0SjCAGrvf6yiqQ(d
zg3e}Pa(a#w^6qEImc9
zmeG=%WuWXf87_Xgj1@drE|%RVeI3CmIGnl}+->W2?Aly|?%}|L&9e693=!HGa+IQF
zNO|Vvt&w!wM;3(`C`QK4a#rQZg$wOgFY~#)Vs1e?$J07IGAf(4)Jzz6Hu5yXEk{br
z*2?Nt3^N30=-O`>r}`NfblGw^JcJy~2QgeLpeJDC#*Id@nQE+LYMTu75AvjjT56W8
zS+iCO3rZzLbyBL9BO6ax51am-rLuLdW&Et=xh_kM@5UlnW-V^6-ezMu?$ibA*3`zE
zmXa+;kDQR6?mpSMy-sqnRB0xu(nLw(q1gGCIdV4KQ6=WQ@)-u#j)HNlr9&3;1>0h>
zyvk10!CTA9&@xq_PD#m>^74(+a;{anx*6|YYm+rlq*$14&1hahkzDEwH}($q>RmDj
z>$2tCc{2*wINWtJWoBwaP0o~cWtGy~(^vnjjFxV>
z^fY=gFhCxPSxeoLIaD{Dx8W
z0_dWj|G?o1Wm#9>7p7jTmLG`8lBZbYK^m#=Qq6FSkg^Aw$VE)x6nOw`HP=!$RspUKJ4Rko4?-
zOnP%)5fE&d5^VA9GM4{*>0J8`>F*Bm5D@JA!Bs8oXVaz{S-B$Bs-&X9mOO;-oXZMZN(k~COAGs$d6-g>GV$%Eqc-6Yc;@tE}**Xn-ho8&?jMeVTd|g@tP(Cv@0{
zf#m|*x9^nP+vCGQcmAM%>^dhMja=JN~fqrd(IuEQ1
zj;$;yTW2$ZUAHfRWhJ?J1u8pkTgdV9z}UdZ%gZlRL$zUotbyxQzf1)#@132ORF>As
z+O_3&;@P0v?1c~(&n_*yBqiV2tZf`DctB-}BNV}0m!-yc{S&M!G&^fiJyIjsuxkc_
zW%g^ndL3?$%0z{XHHk+SBU8N=yUVnb{xzZ`F*0afolF)%x!E}0bv)b8<%zEMo}Qiw
zdE}e>i%kNms;kwDb^EObiX|m2LlsNDokJU7X_e8b6U}B6FzYZ%uqghWJ9kc6r;ur{
zdbH6EN)`jC=~1~P-TVGq`tom+v7(pDV5ySpn%iVJ|AjKJ`OmanoC)sJyewq@0bZz6
zgi*LMWlPE|l@-Qb1A=AjJI5xc><$m#xHh2a4BhuLXU>}ZGl>iNhh$Om%nshXCFmUs
zK;E2*9)Po#ogsSd?%ZHW9XXA(N|4g(99Y(lGX1n*gw|)r=F`V>_@2u!4Rgw
z?!Ascp4>#BC|q8n0USPhM3p7GASq!v>s`GOx^-AK6(Ck>O9DH#@6hzA_o{N@x`^3Y
zGfV$w1|x{if3!@jEF#|*8kFYP=moi0|IgB2@M4j|yJV>3WlFFwk)gsDOW)?dkO4=q
zVOR)3jh01FM&Ta{_Z!NxOg$2I-bv5O3kX)d59*_=Y_0V528WI>bujedj%dUKrPszO
zcmf_3;rPkuk`c<_@`@m?aT4}GR^oL~qHADecqBNIlwk=icXO~btWYCAzp&7@cm?s#
z%?29RjYF`SHc3lmBZP4LPn9IrBOdIL@U)6V;Bh9Yn1xT^S|ngo2Gc`=Zs87XOBp*3
z%1<^n$g#Gd%ZEGdpmBYGX9A3W8;6Va+JF<}m_Tc=zxmYPqq(`%)hT%e`L>gjQ!dUU
z;jG5d1l@#-2~+T@$Wznk9v&yyq|_`aEh~>%%TB%=_&XXL;_q7sn5>SqNN4@uDZ#S#
z^-dWnxm^kN#WJXbJFxBVWoWq7WOy+MHolA;+_i?ijY_atlE!2w^J2B_W@JgW*2h`(
z2CoT(-YecG`&g%h?3qS3*>k#D1vTT1P
z!o++dC+Hrhf1)7~_U$`l6QI&FLJr7TEh(yl*zn`z1OsPopy{|V2$ryQ>sD>7TDaO!
z1M7wU_e>kxxOg!{3#a<$U1Xb$jfdL`anP#ex}sBd4W*=by_!!OcppbQ9kxW5u^h
zf8q0_XZI&nfA^VrC@63|BxE^weBR*7=xSwko|9&>^K5q>)-MJVgI3uRmxjh*&IE|o
z+mb_=toHVc!2~!p=*Q)stq@bCc3W+5Q#^Q9gXL|h=5MA@ec-m`ME?=^i!i8v@gK$o
zA@~ai1&O}A9Ijgb;ZH2_TD>~o#$AmEG$2<@SlqdTj0-3uM`Y8)VtjhveB`s*sm_sZ{8V+D7~Sjmf}uiz%R
zRQEZRHzZi^G!Kc*DNMC38k|Q0IGKnOifq5$u*ZpdV7bbMOp>%AX0w($U5*|-8r*aPfmIe`!BI{Dk7;nK(B_Ns$$k0{+O<#rvg1M_-I+iiL(f-K
zthXgm-Ksc2ML=wR5x7zlbisjw`Aw!n1T!lRtr`YB?Mc)r!l;1`Y=Kq
z9aLALUoNSF`j^r@^6W2G$a9|DC(nDbPG0oHc6rvLyOeNi8txQ3-Ff+I
zN~NotcB6F`A%mp|ax&J}Bwg!&R|)n7O0X}HvBJA#v{(tY@P*R7=OL9lC|2`eLl}!s
zu#|taOt-0LfqYQ@Zssk9a$#|4tXp*{*MS44;v^+;?sUYsOwW+q++4YMF*qanMgelk
zfSUE3K$!3vfode^_ddOBwX1)lF&S(_L}x6Vyi`$FS8q!OSyv6gT1d;bWnq^tx*
z*~yj4@{K{ThYuf?
zJm;ys@+|%S?57Sx@hjWsh!?WnZX}cYSZ8WbbK~-f)X9lP$I6MzQ7~>ruLhLut59
z;7Ds=pkKURnEHYe*MB8;0)SD
z2aULY45pnyRU=Ps=dV-Er)};>8so5`2WuOer02+~lkv;HW+zwr-W!8pckSA#!kuDW
z!_I?ENzasg+es+iYMDCdu^0$-!N%h)@~X!R)mz;z&wk>dJokw`O0)-L+0*+q>{7Db
zCO18yB>Tl0x$VKN^3OR9vgMq6_a$Z7iz-;dX03%$UN=AinviQ?vkphFF5sbXhU35@
zDjJtQz_KCMB}P4Mm(IFyz4X#Ypd3cK4oFYM+hwTmc_G2xDMLlKNzaNA|O)+?ay(;K;-?(vu5o|_IUd)4KXOwm2l`=4h-83^$y@OhF
zLt5)y!=sY2`=s3a?FxDB1EuoZ2e&B6s^<#9K6OBz`{WLJ!DCz0qt(BkIHBI`R{6EB
zRLD1~_RE=Gricd%{rgmCmbSW>KBA3*-D*~kb1m`6W4$Ingm6FV4
zvk1YmUFWuK+ryh3Ji%TS!E%c-Nl8r$7IrJSvJWx4sch8(4Js9H7#&pWORGJc
zD7B}vPd-+0P+t95m6GTNdDdfFm1yha*^f8MGWBSm^JIfO|A}4loF{hM*zEJaP$lnP
zu}3nGUQ$6LA&8vw_$*2jI{SwUe0SHQ2(L}{^I{^}5LoZW^oSWmiT^Ol(R8kMo7hT~0~o})6Jo)c_XLi$ynGP1JeT+8@`xg`sV
zHX1@qa@oG44UsLAruduqWa^6E#5k*IP9?tXJx$X1)fKY+{=bwHFMhqW-tsy*d(XXc
z=EZN4hF^Y<^wtE2gN(q;)2;82U*7u@m84ivy>m>-W^Fg*(0>0NyLz!v)1<(zyhd6HNu=gqj~dze##aepAMBUn*lo
zcgaZc%Vf0pCh01!pYN2M?QpU`xJ250;tGxdnx>!!95VQt!f&0+j&o=%>kueGMilp@RqkEd@8=kM`-m
zUHUm_b4!@Grn0EPrmUdPw7SUWkSepT9lPbk|2{5_Z}@=JzUs|#_>TKz;I{jv=Z?3?
zsaM}CXJ7di+4u4{$jQ$?i3`eG%ph^?bt>RacQ+e;tW3_ZZE^_^EEAoIi`PnDU$7!1
zxSKc49GbrCpI}K>R#ui4q&Co;RYtHWcueY@oH!92BNiBsu0Ruosewv2OEi?i3q!;5
zFU*WnbE)WLjrL`|PK7%d?-{D>psXATM~VPG0!LPI>;9H^_6oP$IwmjSBf;
z&3-vEfc>Xnd$f^Z+kO$D?HTJ=p=9+f5~^aYq|0=7nEgW+9^2kNh;re?y9JC0!2ZP+9OmrdngnxMu}di`hfq_g;y
z!6EBKbPwMlV{2ZZ1p6B4ZLPF>G2Eajn+W1G=n?^P)3E>GWfPs~;#;$()V2^Lx7HpO
zLC&uR(!aBQuMw(~B|ed-;`;SND#IO93oVw-pa^c0VleW9wtfYFsoV(|3
za{iwC9i
zpD5TXcRf-n%O0+fWnZb4=RQ>{&w6sVJm<;%@`6VX$cw(*AU8d^O_n`YA-6oVUOupV
ztE_E07gjO1C^gwB<<~PA8XQ0`j-~4S+?!0GeV7~A9-58
zsalC>>9x@)NF75616saA`e~!3X4q?4t2^rUTIUzYmrtt;)ql)Qfq$doG<2y$E|pfv
z!H<4HcK*We%ZZ!cAeU}^v$Ws&7P;_>w@90k>giYAE3L24Yj@u(=U(*|X}Ra^a^!_?
zkX^s>e(Bsje&WzfapvqfCD&Zr(FuZe$0n{`T@c3!vy&$+m+PNknQ54wo^B+|2|5rg
z;~%SX3+3FoRvYwYBmZDS{{aipY4ZrrbipH7q)ayt#%5W{KPqdEoR!~C-73$2s9c`?
zzz+3h_sOzv?o*O&l;=OXUkP`w{(VT6eYIJZeQ}4p=FtjyplqKU=XjXQ7YUn#z
zARQ&IRC0ZRjIN=3SUuSMTcx++tuox%Xe^A93~qbE+q
zh7nwSAU_Z+C-abAw=>#O!?3o0mUcm?PTrk7Rc)@Z%`_&+Q}~?&GL{Si6=ubY4Mx&P
z9hX`4V6vnCPz4O-)7xhC8U6-_FI|$>f>Jr~SN|o4?|z4zdeQ6T{2gzW*1O*_qa{86`$%T8~DxFHK?RULNTJKbE_Qh|K#=GAxwZHdaIkhrNMtl1LZ{G<{1Sa>9
z;Pg4e2(Db&OoDT&vp8p12{xN^tkr{M7V+xUI9;Yz12bzZKpI})73&CdK#fAjS
z7%bc1m6cUW+1g4eU$?=I&f<{cwQD){Xq_}Q9k=JHsF{GL=vuMv6eGN#vQ8vE23GCb{L&YI(uqYvqoo3grDiDVN;6r=?4yN5u^B9wS#3ZJW4auU$}dbX=14
z8#dXVy&Ut$ti4#!zZrvd%F>O)qHwm>#?Rtgc(4Yxq@={wC`Jhu#h6!ABBd1@q)hX%
zPUXf0&Jy0dd8?hEv((Ucc$IV(zDA_zHW^v-av3dosf-r>jC57LU52~V8&LV6w}lQq
z2sY?yU09)^i5)t0#E!6ATc+(WEZ4P^ZF!{>m9CA+imMM!q*=8p--duJ4omm!6ykhf
zXn0u4D%P8PJ2`Tnx%owxwGaL-(RNc+z1faF1T)n^a|L_^8>!Objg~N}as+A^)b^uJ
z1)bh5#RI3$O6&5~a`Z1hDSKb_PC5GGH%jx%@0FHU-6x%Q-7AB)zezveB&UD&&C>kp
zw@TYxZ`m*XQ(<^_P7%7Q+n+Qz4oOtx%JD1
z^69EW(xENEtVV>-x^W2hx&_6tV<%+A%2YeK!j*A~T8ISpk&P!;BUrt@p=y&V`vp#H
z93a@z($Wb8i!vmQq?<#VQ&Ke#Dl;ZGXJ(q`iEz3^oUb4*CZVbMRQRoc~Fh)W7G$
zvj638le4!dsp@CTE8Z?G_b_?sEzhR%UZFPXz$x3vAT7v-*vA%MN$QdzbH)n;xuGBHb!CJ=q}7e)@ns`zgAPcPi;_mFGaDPpL=y
zl|43o`8g68
z40X}OR8~eAVMAu<=L^bzA;B}PN0E-fn)rYoK+UZI2YyiI0>=fdB
z;7SC`W)rN7wWT|n@4&0lpx2Uym
zr=)oDMZYB{)dSu8bMKN}@BgT@WEM%^&IURC)gQ^BxBiVBRZsQQOI|PScfVaO-2FCb
zeZ||PjQ%2P^;O>oW1X8kciy;StPmObTe-YZ8TvPZOfu$;E$33i%@5^QuI
zP=ZtT1R8Tz81PC;i_4|AdzM{(Ff
zcBd@++9|n7N%rQ)s^z99lvtlQWW@Tcr*_G+pRAMTsu%mb$M(u|H9Y&ted@{9$gh8E
zqwMa$)*MtttH!~QDqekMpnew)Cr+HSS)O=&rchLvqvf6`;2BmzunVC~u7Jr1mSDpR
znkVa8iVMj}>9Rju_O)<8rc_2pf_g?;&HwD*BVG0XBp27bTKbD_m(dcu*V}CTb+q_)
z8MEW+UMiP1{gDiJY&7W@)PF}Y09i}1u;L;^Mz9;zYt5WcrjTvAlc7jGSY4>`Mmu!`
zyHv+uuSl@`t@(88F|D0g$h8gW_v{G>7UFQ^F>j#g^cB3t-lSwkTO8EDPwmw^Wyjn9
zS{h&cS|!!j%lVhTQMzCDX6by{Tjc!9?vrD;zCn(><{i@X+wYggSKKE@Ui>;~zvC_H
zoxWXKm0-`Q*Lq&BU%2aDxpen^a!I|_Gq=884&3$zIr!UuCddB!NolLuDg8stRSsZX
z!N|5I$mBY>d{vO{>gp{@uxXN=4WVMlL_F9k=u+zqs2o_V
z4#=~fJffsprzBgigu3Ulux*F+8Q2|3q?Px
z9_uY4#V;{ZWd^YeV{2|#kM=fcTm3RQzvVw?+&59l<9sUYNp|VM>N9ejQopx={|(u^EVhU=;q3?@H(QP~O0tFN_4noHj({RI%|
zOD7O(5V-bok)pd~sOUw~Ui9m#KvVVk0n9Qxcp{8+!7wy5ssy`H+g*~C=Y+D=HtLpi
zO{fd5rDx0O)2Cf58m=vZO;bhBjzaNah2}jeIaR%>phsju+5)c#i_gCDPJ$X-XCD8d
zG~E71>3Zo~WbkG8%7s_lE6ql*_e=X-_bY+EUCzEz!>g2J_1eWd-!5Hu@b{bK%&Xrd
zZFjvzTGg99s-Es{y?5W+{$5UeZMpOwVIrxvb^X`o0N^e6>!&&fGl5(3xdqbhbS<^c~XQ3X973kRyX`Scmv3wFzvnpoLVuC&j!YV5`vWlWaK%PW$$
zHYUN4-la>h>(*~Hf^`$+NI#q1R{E6Fkoxa*GlrAtY+
z{qFmuRf)Nou3){V{trJYCsJ~y>iJDc*t1vDtsPZH3h$$(Sje%4lghC)>C0lp2*G
z0%f~-igv~l+LQl5(Dsipq-6gB@4s
zc-UJwQcv%(9O*w!UKYa;Fz{L}-;r>R=h#4(bkzKV^sQMYQurbnD`L#`a)M}r<5C4y}WEV=`S$Z1+B1Pw-
zrqFhT`KrBW`7-AdoL9Y%=gK5Zh&Ic*hauR!*b#^UW|yKHf?!))TO}(iTfJDdAhQF4
zrF#jbelk1@mdXw5VL?ErNU-M#l*;$uFB3E)$5Gke-X*{BjdGhI%&t$*f4o+`*n_qi
zMIw@2_N02bU)&&HtEO8?<7L7M%9o63dfdaBkX
zJWjA<8iq<=>aW^lI(;E^kI;pGS~~3R*&`}a_NwsvvE!#~44(;4MzEPGQ)$_<
zTAi*77Xqg%0I8WdRHm<%T-!{J`W!DOeKo=}fg!?PgQM|Q|-zEUY$
z&$E}Nin7fj)_3X4%rjm{=}!pL#xw6tygE9p}2b+qsmO0ai_#2QR;Vx#{N
zCEUT%mrCziCOX|E!>eB+7pmSaLjzka4jZm;m9;={Wyb8!`10egU3>OU=HY(Ug>}ca8bCc+BiPhzDJ&=s
z_qGPyJv({QG+h4#+uhx*f?Q-X%52u2S}dvh$${(j+He;O<7$k55pPqGCU~P`K_zcE
z(Iu~WYMt#*yzHxuN~Zhe*-x`fhm&~rDCsuJO>D3DlzO!ftdWPyYB{=HtXL
z!J@$|CQR5#h~nJ&Ry+0$Z^U`81pYqRe8%osEV#zKZ(pO$;v`*Bg~*w;m%2iQxKv5Tk>ZRUovxY~CZf4X3p|#51z`MEZP{i9PL!b7E4rexQa!*xx?SBZMeI9x*m^*s@`QoO
z)_gbsU_$yAAuqhq=_Ec~4^+?b7TNQzzm*d&{T*q)=PfpixZ}>Z%c)nrOU~Z&yGpL_
zlr|;SmRH^l`F|f8B$WbHf|mTX`DIqo!39XQefrf>m(&5)f%Wf50(bX1QnYt
zH&?Yf2S5-;j2wgNeP+*bdBtN{vW$%=9^EU?`?8YhWBb*UJ*XaSoh*B3y*&ScBKf<#
z-Eyk8&n!<)t_a3>5#`y6$?RbbC=~D}HlbiVEmSs+V5yt)HlDWlIC`u}Qq=&9c1b#q
z`}Dc!UZsnTP1{2Nvt_T7!J_BNSn;jux!xvYB`?%)vwpu-hKo55_7x(<
zFP72LWztss3h6%jQFBU&v
z+O~a2M*9z&QZ-}K#j`|kv8%^=4ki#RGNT4EGi||=X}go4wf&-Gtu9b`iW?SDBVq5}
zpcie?^T6xFBp?Uu2IkV#z4w4@d+P_~$gOXb(@LyOKlf%i|Ef1i$K7wx@J6|$pM5WX
zvvj@WUfFfWTcqiUpQs!KZE4BWO-P)a_qwLIOj6Ql+j+LBN3i!nrtG?Gl4X#GnL_h^
z{Szz|yr;fiQd84ZsIh)&q)M>bU{|fql?!dbp!U)c1Wn8En0lc@GCbC;f*Op5oE#XD
z75mP}gXDmU24B8v%^&aSRb$q&!0bqbO3`xPk}cJ$cNL0Ip6*f>^D-$OkI
zrDf-b)H}UH`igFsk-|G=tl$ojq8HoD;o;(C(yl~%VZ&d_P+OHgj6p^l2%>X}b}69w
zY>RoU&e%a_tOrENs;Q~T?pZQzcM^1~;aFI@Zh|}!SPHg9jejS1iwcU6WLQxK#uj^;
zbG$ivq_v`2w%q$c*?-GxrQ;=Ukai{2v#)xCT)O8?(tgJq2A(^2^SD)QS!%*=2A__Xn
z&nb}Zo^G`sOVt~hsAwSA&D(Y?x}xO$grT89JM{;z$$77=o91uUWLg(~c>iJ}NCD~T
z(yCTtON$zw9qHdMefuAl_KJ5)TiHEwsqEQuvE*6OQTj4zU;C?aar?()xUJs0&Uo7N
zk5v=hCqaEJ1=R1|Z~IhJ2TopWnVl-h^Ana-EL{w#H@9)~R+FEo+%r?1O-)=c+M)v)
za6y6LKA?shTNWZC=eKQ_gMa(q()0_zCr9qQSDIe@J96rlH^}y%yI(f_!QaZMZzjpe
zg^RW;U9Zg?wP=XLjvC^~3c|uucKCsh5hk
z%BdXAgH6xMk)-4lsolO)@3Y&M2((i1UJ-8oB5kVk#)i~G8RdWg>Wn2ggL+*F)w+`L
zUV^CuCe+a|{$fy}kX35H)xSkQk3Bm3=v@~WAyR_Es*d4504881h^(VU!_xid^$Bpb-)5`d+Pf5bL3VV~#m{hw8)QnIBWzgW6D(XCO;E(a=?H--nxp}T9>
zt&^20G}Jr|YPrx*Q`2PKy2=R$tS=lwX|zB^25Qa3fIrQx(7#nM@J3O43~P)I>ficB
z)u<{){ZAjTV7GIxKEppaA{qz&Nnn4D!``uga0;+~PrV9v&{gl03`!?^b-tW)>(3TR
zS;i~rqsNZhT1&Rn{tgIEIkuHDm-?p+kh_55-eMCZdOB%Efyyt{_p8Qb;FI}!SY$VZJVSfXQ&62X9}Ki9cHrTy}}{5_ce+{hFqsU?K}$FLbyUWV^{f3pTY-A(zKBnDc
zT;n{2gMUz4NHtcoo0b$K;m4gwVTAKOIbN`nG)3i50>8`i%Y>}Z(7J`~))U53WudM`~S}A0B;jQix%2FXO|7Ufht(LAMg^vEHzS<5d5<>uZza
z)oT1z{Ey3vhIP4RRa};ng*#gMJ}gz0>pz?vCRdY78)|yO2t@M;cM953th|8#rW|`K
zV0e>mpRUz-G$p5@XpKz1HMJ09siLt~04=nB#HYnZ;ZpbgjsYem`J>@`($H)4+%fA)
z%>qiQk@}a$2Yf{L4pL}v`|}l5Ccs2Z?4K6Ru)s@DDZVj
zRW9?M{HF(^6Y1!Ul-;avgfA)L31sNYs7v0a()5PP6CHx+o;<_*s_i
zT4d;Y3vved1ZEi3_Ksx-c}4fX3%I{;djkiV3~G35iWC;I><{ac{Gm7bIHT7D0!_mH
zL*Byi$clj5+8|Z$_SN!K_Uz9eME&d2bXr+ePV0b5#j>rX&XU7`_wJHCll5!dkL^&s
z7Uy)oh=1W0$TW>a%#uQ!_5wNA&He>b)0d#970>RXZEqcAyhaufs;0*n5^UKGvWAE*SG_4HXpc0wcoi)5);<
zL;ik4?p8CK+0}T)TX=-^rBv>qJTunkiO+lv!Gdy|r)OelRd}~2(qCg-TQ$K*t6L+3
zfhj)M{SW^OhwJt>xt`Jau*tK_AQ}SggqWzK3D-5g;TQJVxg3G?>Z>6nv>~|=O55P8
zMsEQSR=Saw0&8KbcH7^7^1S9zbn(ozysd9idB#6zZg`EPiw9p{5Q>YN1&OB7$BhPM
zxjiD~hG{b=OFov`9irK_MLQPkDpL0Mjis>LW}&1EYgC6k59N*fjje}q0p8wWkdAZn
z_rku(ZkG7nziJS*k0W&4Ty1#v31Omr8GrHF44jVtOCk}W%kEZ@`wX!(!EEM>j5>Mj
zJ<8~z8g9v(RhFIb20e3n(gTsf#Cl!8AnX7PoCnvvJH#}fl`Y_I2v0d~7ue#`
zf63HG&s4giTgRV3?g!bVH|5%-jX_Ls;Z)xn?%HY!)#6nYdYrELl7nN_b5X
zV?UHhY7z`WX+DI7MD5BO6;XW;F;SFb-ZwY^;6EsjXQ>IBUie^#y)-0m%Slo|Or{wQuoT+_c?&lNW
z1j09RkObN`m$kMU<5D8{Irs5$6RU|!t}%>+S5#}`I!VR?XL4VB`xTa8>6*yY&NGh|
zI-cE>0}kl3n?pc#>&ncXhbRsT;*m29xbK+)TLr73=81U(NUzg3id!MYRtG*RmFWOF<}9J^@DWT
zUre!umn6!(vOUBBmsd%){p)PY;{Z>}Tq^{iRl*ih2dTZ24fDByNE1oka0JY0%bXdM=;3uQY<>*zox`us2
zZothADqz>lS^hYPxBPdWO=}V(B72|)xlu+ogPzSXN$c9TerGv2JQQr~Qw?L~rA6S3pl@2;!eio1s_GS!Qs^-K(M=NwoFq*^
zCfq8PJyQT!?+NVhhHj-ypfTWek~R)o2>DCuO~w=J0(~>CoJqKT`~xots+Ad>|2t
zC7j2(uKmA4cr2$&j?EY9;nUm4oK4|E#F~a%}WBlzens8)t4DO|2
z9P^{IjZ!25b9&Apgt5lnU9ZLU_4A9f?C`d*a$<~p`?hdm<$o>$eP17B#Kd|hZ%m0|
z8wSS4P_Y#I(&_7w@YT#!Wko$G0Y7`D{l}`3vih18Q+*30Q+*wpm|m+x!yZQ)5!!&v
zMocLqJb4_2M1<#a!!x!GTrLphLhUk@$nEow9>*f4*EdaHhc>^uCgME9n<0*8{T0j(
zF0QXGOJw%({Hi3QN736f&qP9iiHGZ83l%
zMWymxt0co3Uz*97`<$d$gHK9aNE7#C{b*b?HuUUheES44p1TbP()e9=cm5R3UxT2r
z2>km&?#gxP$F%^qe@mz#M
zB+FL&i;Dg7YoaFBd^FI0`!z(?&6?I+8x#NpkN4p!c<1UyFs^=#muYTzgJv1xk<|JS#QCsMl-^#>kYKTBO{Km*YL8g-RE*T(sx7;
z<=?8GD%7B6_;lyxDFx_xbM41`jv=*&+6);BjA?RB~meupDpl#W|pl;&QH3b*Z7bDC3?fdy&5{n$;mQGMl*=Y
zKc+xNUl9q{hN8sUNaWm(X=r9n6ABHb8%jxkZL~PIVL~r)G-Fy;YGj)?Va;izYS-ao
zjL3^JKx>rQyH4=$+ue-*epLi-KJW6}Y;&u85t=WQv?t&bJziYpx34+(zx+Wi)}>-Rt(Nb?tK<
z>?Yec$30xcoHEW);0_Zp*mMGgCMs;qBv{Kczdz?_G(KLu9;}}`Caa0K=ViCww}9?O
zm!5#oH&9;aTrz`t!c^zHJz}elzCA=f@0Y*`|BpbTm$2#a+O20HYwwlQ;=PVOdQ`_(
zIk2!7l_mqrKenB?s=Z?sZf(^>YPFaKJC}~u>E>p;H9e2>)q5Hx0ry41j#4YWwXb5U
zWqus`?PY#GRkB+Wf(YOJKeBoBsmD=h1Y+VY$wo66{`s^evEE&7dk7@|hs6}w&|b(*
z4Z_YX=a@r65H#QX!#v&JhL_SD08k2;#qP~tjia1*svk!Buu
zmUtx8XqbBGOgp8Y2*P5%0gbpbMDUD8kr>b_K~gLBFiih2R(vb8gp(V@a$oZkFLB$(
z3H#a<2)vr{XU+M>AYrHc3{`@_c5ygf`V5`c0EuJhar$(@znfJ$Rm+!Z<2rQ+<~0Wy
z6`Kx#$oVRHER_AKGTkR4WN&RaoS`W*9)1Apt%676%KuJXjjBju^e20(J}PvZ%h6!&xAbdY&~WTJ<&=
z*0$~+0e+`E_{2oX2_JrZT~1N+8?R#E_5(w{x80@j1gT!@AN@_z-2H%lk$`ZeNGrdf
zB+z2HNmk(tJ`7%lN)a`alGhh~ftd64-~f4@s-}M!5^KS?Mn^ah>`0h#P$Yf}d&6WF
zZ`MFCV)j*M14gIWudYXJx(1O0l5tfsNDsB|KoHmkg0PGgRqnif6H
zv+v|(_JFVMD2Q{SAN)!(cg`9&)vOMwq!%a_gt0PpZ;oI$od?kx!P9`6o3xIugTk1N
znSLB}9gO
z{A%)r8&~hq;jxUIZ1oNZwV2^r#Xt@=8TkNaDtm}dO-E(Ln5GId2!4O4^L2MW+<~rb
z@r9OA%`QvO#(4@*alp-9tB7wkp0rpAsr7-UrM6Eie{{Gb3059B45gYj@-_cv4@MTTc}B$H4BlyxKQ7aPSBA|3p|^xD1I@=Fm#5*
zUeJ3SM066EPRAJS@$u7}S~{M$h8ben(RK$J1Mk
zv_^MXfD7lX=0tQ=GLZXW^x0Dn`dCBSTPl%f%9ycDgu&4x8BangsX1_`Ym0%_(X;2w
z<5FaFdqp&i!z=`aAl!vu#pD-5ClxcZLZh>~qm(()5#2nvn%8Ym0K*RFCOMg6VL>k%
z{ScY=TR-$7AV6(WzEfoDM#rB=dKfYTd)z`19`)&s{v6)ry
z!6w+i2ih@c|J{8yVEZlyfp^q$iL~B3UBRa8TzjurzBCV=;2}b-tfanteppNA;+xB}
zNxW6ZPRDRc5uC=iXj{iE5_tw^lZt?Ar&I~3)ZZyucFIN3F|zZ}kQ@jKi*{Z37_uRO
zp|p%nN4C%sf6&)l3a;H=WZBx3M>)sM91dlls=I~HATM$U%W7jEJC|Z5mh&eid|o@u=){(6T+vA*rlYQYJ*1HKlzZ1)oud()v29lG}Cs3{NvBsZe#PEs`
z^kfU!S=8J=Fzvl!fu@%j&1k(?O&?rcT@#D;$DE3fQ?2+U#gmP}v1L+?CFXvQjf>5j
z(y&$7SPb$OVH}%-30hb^3)g=SFMJBAz>0=_1q?jnaSWl|7ON6=+bW60r2jaF36@PP
z5RB9fhM9m+U=XQD(_#Jk!_XIU2O4O9~v=ZS+a&T_8&UF1`W1Gw$r4sKLv(*5JN>#rSA}${D2JDTo*RX(+358O2NL
z5(^f85GGl2IeNG#W0RkjTua`Rhx1nN{``X>~Cu5LM&p`LpYyp{}GqG3K!IhLS%ZTF#s&(h>
zB!IkbAh*R3Q=@c0_&4{zql`ZK@iEyH+RjBvAz60(!nD6AI8*+UoMFbdhXl^?hm|N;
zVtc*)!^V`F5GooiwFV<4!}9DOP;q0r`tK)cH9G~$-vew_mF(1*qjc;=>+*|sF*b27
zC$Art=TM%TY3`$qQV(Nted;tKo1PSlY$ISFVn{3
zzIx}&aLR!yoPzKZD;;t7@;%`d|1zDApd**@Od<=EH2nu>}J9|glFzQ^PERv2_S
zxer1!w#zn1GHZxKyIY>+V1wF{=e-2QVD%UGI`0gbJ)tleC73mBC-GA$bS=_eztxBu
zp56G7)yQ$ov|&b10)V^O%N6dhQpnx)s-!OEmi5J+
z@53=qZDG!_ICA>$gljMQ<0CNP^QoFh>#Ohsh<7wZ67?;}@!`JGs(S2%czaOMwg0MR&fO4=Ksa?Sm|dn(7?qVL1Uj{g(MT@R&{Ko~
z9=19~xO}jJSGpr1CZ!7l&JZe1V@aNDYrO5YQ54ZRNuvKaWSq#yI*G~KC9V6oLDsXn
zTLs>3&?IEjzpzWs@O6&)q~9SaO{7DQL9yXqxB^{Z%{ftkNC3iX{MWNIp0Saoc{t6i
ziZPw9)g?N6V%MS2ksvF6H}#vSFQ!?U2>V#URM>ACp3eY!0KuecNRgJRbWYIWoMnwS
zC$;bHOkh$PgfH21)STK-1q=ah{eENzi|COLmN}RBf5L#8E`;$XKXp2iy~|v9eKyT(
zjhiJpTR%dgEqdkQm);=m*US=!@aEY1J={SOagaB^j8~)){k!LMYVPXvXga>lpW4HG
zL5nD>9(Pwa8CL~+HccD?##;U7snwwx0k;+Jk-S~KWt>{}c=xnVWSigyA6Ux3Zpje?
zom;(hEvAu7#b{R4d8Q_PTb4Bin5k=(XA(^5<=uz;?*UaEA??>%CQXmqML%Jz<83H
zNpNzU${*Y5y<=PQ3~576MG|x7VI6d5YR#O>jK!|3em;lJKCdeMF~(9(hYnAC|_!dA>zNZwv0S
zb5;IEQ(Mo%eD9I&z=ox66_(!J8qfpCef)5#TPe15f2HXi72)7tU7u8J-<4L$hpRtT
zP7DI`rr!e6AdNOfkL!rpQ4eWyX_mi~;>RNCxagiqS8Tylr=H7>e51ud1^J9re@kbm
zuf;?hmYs1kq+q+^cWi$yRu?V&YZ~(qhTsx)QG&?25UtDo60LN?*8HcCPHH;a;N@|I
zaT>ZNopJz{X}ZqP)wh9Qt6BCV9&01_