utopia-ui 3.0.90 → 3.0.91

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -139,7 +139,7 @@ const useSetClusterRef = () => {
139
139
  return setClusterRef;
140
140
  };
141
141
 
142
- const LayerContext = React.createContext({
142
+ const LayerContext$1 = React.createContext({
143
143
  layers: [],
144
144
  // eslint-disable-next-line @typescript-eslint/no-empty-function
145
145
  addLayer: () => { },
@@ -167,13 +167,13 @@ function useLayerManager(initialLayers) {
167
167
  }, []);
168
168
  return { layers, addLayer };
169
169
  }
170
- const LayersProvider = ({ initialLayers, children }) => (jsxRuntime.jsx(LayerContext.Provider, { value: useLayerManager(initialLayers), children: children }));
170
+ const LayersProvider = ({ initialLayers, children }) => (jsxRuntime.jsx(LayerContext$1.Provider, { value: useLayerManager(initialLayers), children: children }));
171
171
  const useLayers = () => {
172
- const { layers } = React.useContext(LayerContext);
172
+ const { layers } = React.useContext(LayerContext$1);
173
173
  return layers;
174
174
  };
175
175
  const useAddLayer = () => {
176
- const { addLayer } = React.useContext(LayerContext);
176
+ const { addLayer } = React.useContext(LayerContext$1);
177
177
  return addLayer;
178
178
  };
179
179
 
@@ -428,7 +428,7 @@ const useVisibleGroupType = () => {
428
428
  return visibleGroupTypes;
429
429
  };
430
430
 
431
- const ItemContext = React.createContext({
431
+ const ItemContext$1 = React.createContext({
432
432
  items: [],
433
433
  addItem: () => { },
434
434
  updateItem: () => { },
@@ -528,33 +528,33 @@ function useItemsManager(initialItems) {
528
528
  allItemsLoaded,
529
529
  };
530
530
  }
531
- const ItemsProvider = ({ initialItems, children }) => (jsxRuntime.jsx(ItemContext.Provider, { value: useItemsManager(initialItems), children: children }));
531
+ const ItemsProvider = ({ initialItems, children }) => (jsxRuntime.jsx(ItemContext$1.Provider, { value: useItemsManager(initialItems), children: children }));
532
532
  const useItems = () => {
533
- const { items } = React.useContext(ItemContext);
533
+ const { items } = React.useContext(ItemContext$1);
534
534
  return items;
535
535
  };
536
536
  const useAddItem = () => {
537
- const { addItem } = React.useContext(ItemContext);
537
+ const { addItem } = React.useContext(ItemContext$1);
538
538
  return addItem;
539
539
  };
540
540
  const useUpdateItem = () => {
541
- const { updateItem } = React.useContext(ItemContext);
541
+ const { updateItem } = React.useContext(ItemContext$1);
542
542
  return updateItem;
543
543
  };
544
544
  const useRemoveItem = () => {
545
- const { removeItem } = React.useContext(ItemContext);
545
+ const { removeItem } = React.useContext(ItemContext$1);
546
546
  return removeItem;
547
547
  };
548
548
  const useSetItemsApi = () => {
549
- const { setItemsApi } = React.useContext(ItemContext);
549
+ const { setItemsApi } = React.useContext(ItemContext$1);
550
550
  return setItemsApi;
551
551
  };
552
552
  const useSetItemsData = () => {
553
- const { setItemsData } = React.useContext(ItemContext);
553
+ const { setItemsData } = React.useContext(ItemContext$1);
554
554
  return setItemsData;
555
555
  };
556
556
  const useAllItemsLoaded = () => {
557
- const { allItemsLoaded } = React.useContext(ItemContext);
557
+ const { allItemsLoaded } = React.useContext(ItemContext$1);
558
558
  return allItemsLoaded;
559
559
  };
560
560
 
@@ -838,6 +838,22 @@ const useSetAdminRole = () => {
838
838
  return setAdminRole;
839
839
  };
840
840
 
841
+ const PoupFormContext = React.createContext({
842
+ popupForm: {},
843
+ setPopupForm: () => {
844
+ /* empty function */
845
+ },
846
+ });
847
+ function usePopupFormManager() {
848
+ const [popupForm, setPopupForm] = React.useState(null);
849
+ return { popupForm, setPopupForm };
850
+ }
851
+ const PopupFormProvider = ({ children }) => (jsxRuntime.jsx(PoupFormContext.Provider, { value: usePopupFormManager(), children: children }));
852
+ const usePopupForm = () => {
853
+ const { popupForm, setPopupForm } = React.useContext(PoupFormContext);
854
+ return { popupForm, setPopupForm };
855
+ };
856
+
841
857
  const SelectPositionContext = React.createContext({
842
858
  selectPosition: null,
843
859
  setSelectPosition: () => { },
@@ -861,7 +877,9 @@ function useSelectPositionManager() {
861
877
  }, [markerClicked]);
862
878
  React.useEffect(() => {
863
879
  if (selectPosition != null) {
880
+ // selectPosition can be null, Layer or Item
864
881
  if ('menuIcon' in selectPosition) {
882
+ // if selectPosition is a Layer
865
883
  mapClicked &&
866
884
  mapClicked.setItemFormPopup({
867
885
  layer: selectPosition,
@@ -870,6 +888,7 @@ function useSelectPositionManager() {
870
888
  setSelectPosition(null);
871
889
  }
872
890
  if ('text' in selectPosition) {
891
+ // if selectPosition is an Item
873
892
  const position = mapClicked?.position.lng &&
874
893
  {
875
894
  type: 'Point',
@@ -1134,7 +1153,7 @@ const ContextWrapper = ({ children }) => {
1134
1153
  // eslint-disable-next-line react/prop-types
1135
1154
  const Wrappers = ({ children }) => {
1136
1155
  const queryClient = new reactQuery.QueryClient();
1137
- return (jsxRuntime.jsx(PermissionsProvider, { initialPermissions: [], children: jsxRuntime.jsx(TagsProvider, { initialTags: [], children: jsxRuntime.jsx(LayersProvider, { initialLayers: [], children: jsxRuntime.jsx(FilterProvider, { initialTags: [], children: jsxRuntime.jsx(ItemsProvider, { initialItems: [], children: jsxRuntime.jsx(SelectPositionProvider, { children: jsxRuntime.jsx(LeafletRefsProvider, { initialLeafletRefs: {}, children: jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: queryClient, children: jsxRuntime.jsx(AppStateProvider, { children: jsxRuntime.jsx(ClusterRefProvider, { children: jsxRuntime.jsxs(QuestsProvider, { initialOpen: true, children: [jsxRuntime.jsx(reactToastify.ToastContainer, { position: 'top-right', autoClose: 2000, hideProgressBar: true, newestOnTop: false, closeOnClick: true, rtl: false, pauseOnFocusLoss: true, draggable: true, pauseOnHover: true, theme: 'light', closeButton: CloseButton }), children] }) }) }) }) }) }) }) }) }) }) }));
1156
+ return (jsxRuntime.jsx(PermissionsProvider, { initialPermissions: [], children: jsxRuntime.jsx(TagsProvider, { initialTags: [], children: jsxRuntime.jsx(LayersProvider, { initialLayers: [], children: jsxRuntime.jsx(FilterProvider, { initialTags: [], children: jsxRuntime.jsx(ItemsProvider, { initialItems: [], children: jsxRuntime.jsx(SelectPositionProvider, { children: jsxRuntime.jsx(LeafletRefsProvider, { initialLeafletRefs: {}, children: jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: queryClient, children: jsxRuntime.jsx(AppStateProvider, { children: jsxRuntime.jsx(ClusterRefProvider, { children: jsxRuntime.jsx(PopupFormProvider, { children: jsxRuntime.jsxs(QuestsProvider, { initialOpen: true, children: [jsxRuntime.jsx(reactToastify.ToastContainer, { position: 'top-right', autoClose: 2000, hideProgressBar: true, newestOnTop: false, closeOnClick: true, rtl: false, pauseOnFocusLoss: true, draggable: true, pauseOnHover: true, theme: 'light', closeButton: CloseButton }), children] }) }) }) }) }) }) }) }) }) }) }) }));
1138
1157
  };
1139
1158
 
1140
1159
  const useTheme = (defaultTheme = 'default') => {
@@ -2603,7 +2622,7 @@ function fixUrls(message) {
2603
2622
  /**
2604
2623
  * @category Map
2605
2624
  */
2606
- const TextView = ({ item, itemId, text, truncate = false, rawText, itemTextField, }) => {
2625
+ const TextView$1 = ({ item, itemId, text, truncate = false, rawText, itemTextField, }) => {
2607
2626
  if (item) {
2608
2627
  text = item.text;
2609
2628
  itemId = item.id;
@@ -2679,8 +2698,6 @@ const TextView = ({ item, itemId, text, truncate = false, rawText, itemTextField
2679
2698
  return jsxRuntime.jsx(MemoizedVideoEmbed, { url: href });
2680
2699
  }
2681
2700
  if (href?.startsWith('#')) {
2682
- console.log(href.slice(1).toLowerCase());
2683
- console.log(tags);
2684
2701
  const tag = tags.find((t) => t.name.toLowerCase() === decodeURI(href).slice(1).toLowerCase());
2685
2702
  if (tag)
2686
2703
  return (jsxRuntime.jsx(CustomHashTagLink, { tag: tag, itemId: itemId, children: children }));
@@ -2748,13 +2765,13 @@ function UtopiaMapInner({ children, geo, showFilterControl = false, showGratitud
2748
2765
  const setClusterRef = useSetClusterRef();
2749
2766
  const clusterRef = useClusterRef();
2750
2767
  const setMapClicked = useSetMapClicked();
2751
- const [itemFormPopup, setItemFormPopup] = React.useState(null);
2752
- useTheme(defaultTheme);
2768
+ const { setPopupForm } = usePopupForm();
2753
2769
  const layers = useLayers();
2754
2770
  const addVisibleLayer = useAddVisibleLayer();
2755
2771
  const leafletRefs = useLeafletRefs();
2756
2772
  const location = reactRouterDom.useLocation();
2757
2773
  const map = reactLeaflet.useMap();
2774
+ useTheme(defaultTheme);
2758
2775
  React.useEffect(() => {
2759
2776
  layers.forEach((layer) => addVisibleLayer(layer));
2760
2777
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -2768,7 +2785,7 @@ function UtopiaMapInner({ children, geo, showFilterControl = false, showGratitud
2768
2785
  if (!init.current) {
2769
2786
  donationWidget &&
2770
2787
  setTimeout(() => {
2771
- reactToastify.toast(jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(TextView, { itemId: '', rawText: '## Do you like this Map?' }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx(TextView, { itemId: '', rawText: 'Support us building free opensource maps for communities and help us grow 🌱☀️' }), jsxRuntime.jsx("a", { href: 'https://opencollective.com/utopia-project', children: jsxRuntime.jsx("div", { className: 'tw:btn tw:btn-sm tw:float-right tw:btn-primary', children: "Donate" }) })] })] }), { autoClose: false });
2788
+ reactToastify.toast(jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(TextView$1, { itemId: '', rawText: '## Do you like this Map?' }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx(TextView$1, { itemId: '', rawText: 'Support us building free opensource maps for communities and help us grow 🌱☀️' }), jsxRuntime.jsx("a", { href: 'https://opencollective.com/utopia-project', children: jsxRuntime.jsx("div", { className: 'tw:btn tw:btn-sm tw:float-right tw:btn-primary', children: "Donate" }) })] })] }), { autoClose: false });
2772
2789
  }, 600000);
2773
2790
  init.current = true;
2774
2791
  }
@@ -2781,7 +2798,7 @@ function UtopiaMapInner({ children, geo, showFilterControl = false, showGratitud
2781
2798
  // eslint-disable-next-line no-console
2782
2799
  console.log(e.latlng.lat + ',' + e.latlng.lng);
2783
2800
  if (selectNewItemPosition) {
2784
- setMapClicked({ position: e.latlng, setItemFormPopup });
2801
+ setMapClicked({ position: e.latlng, setItemFormPopup: setPopupForm });
2785
2802
  }
2786
2803
  },
2787
2804
  moveend: () => { },
@@ -2852,13 +2869,11 @@ function UtopiaMapInner({ children, geo, showFilterControl = false, showGratitud
2852
2869
  layer.bindPopup(feature.properties.name);
2853
2870
  }
2854
2871
  };
2855
- return (jsxRuntime.jsxs("div", { className: `tw:h-full ${selectNewItemPosition != null ? 'crosshair-cursor-enabled' : ''}`, children: [jsxRuntime.jsx(reactRouterDom.Outlet, {}), jsxRuntime.jsxs(Control, { position: 'topLeft', zIndex: '1000', absolute: true, children: [jsxRuntime.jsx(SearchControl, {}), jsxRuntime.jsx(TagsControl, {})] }), jsxRuntime.jsxs(Control, { position: 'bottomLeft', zIndex: '999', absolute: true, children: [showFilterControl && jsxRuntime.jsx(FilterControl, {}), showLayerControl && jsxRuntime.jsx(LayerControl, {}), showGratitudeControl && jsxRuntime.jsx(GratitudeControl, {})] }), jsxRuntime.jsx(reactLeaflet.TileLayer, { maxZoom: 19, attribution: '\u00A9 <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors', url: 'https://tile.osmand.net/hd/{z}/{x}/{y}.png' }), jsxRuntime.jsx(MarkerClusterGroup, { ref: (r) => setClusterRef(r), showCoverageOnHover: true, chunkedLoading: true, maxClusterRadius: 50, removeOutsideVisibleBounds: false, children: React.Children.toArray(children).map((child) => React.isValidElement(child)
2856
- ? React.cloneElement(child, { setItemFormPopup, itemFormPopup, clusterRef })
2857
- : child) }), geo && (jsxRuntime.jsx(reactLeaflet.GeoJSON, { data: geo, onEachFeature: onEachFeature, eventHandlers: {
2872
+ return (jsxRuntime.jsxs("div", { className: `tw:h-full ${selectNewItemPosition != null ? 'crosshair-cursor-enabled' : ''}`, children: [jsxRuntime.jsx(reactRouterDom.Outlet, {}), jsxRuntime.jsxs(Control, { position: 'topLeft', zIndex: '1000', absolute: true, children: [jsxRuntime.jsx(SearchControl, {}), jsxRuntime.jsx(TagsControl, {})] }), jsxRuntime.jsxs(Control, { position: 'bottomLeft', zIndex: '999', absolute: true, children: [showFilterControl && jsxRuntime.jsx(FilterControl, {}), showLayerControl && jsxRuntime.jsx(LayerControl, {}), showGratitudeControl && jsxRuntime.jsx(GratitudeControl, {})] }), jsxRuntime.jsx(reactLeaflet.TileLayer, { maxZoom: 19, attribution: '\u00A9 <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors', url: 'https://tile.osmand.net/hd/{z}/{x}/{y}.png' }), jsxRuntime.jsx(MarkerClusterGroup, { ref: (r) => setClusterRef(r), showCoverageOnHover: true, chunkedLoading: true, maxClusterRadius: 50, removeOutsideVisibleBounds: false, children: children }), geo && (jsxRuntime.jsx(reactLeaflet.GeoJSON, { data: geo, onEachFeature: onEachFeature, eventHandlers: {
2858
2873
  click: (e) => {
2859
2874
  if (selectNewItemPosition) {
2860
2875
  e.layer.closePopup();
2861
- setMapClicked({ position: e.latlng, setItemFormPopup });
2876
+ setMapClicked({ position: e.latlng, setItemFormPopup: setPopupForm });
2862
2877
  }
2863
2878
  },
2864
2879
  } })), jsxRuntime.jsx(MapEventListener, {}), jsxRuntime.jsx(AddButton, { triggerAction: setSelectNewItemPosition }), selectNewItemPosition != null && (jsxRuntime.jsx(SelectPosition, { setSelectNewItemPosition: setSelectNewItemPosition }))] }));
@@ -2902,653 +2917,143 @@ function UtopiaMap({ height = '500px', width = '100%', center = [50.6, 9.5], zoo
2902
2917
  return (jsxRuntime.jsx(ContextWrapper, { children: jsxRuntime.jsx(reactLeaflet.MapContainer, { style: { height, width }, center: new leaflet.LatLng(center[0], center[1]), zoom: zoom, zoomControl: showZoomControl, maxZoom: 19, children: jsxRuntime.jsx(UtopiaMapInner, { geo: geo, showFilterControl: showFilterControl, showGratitudeControl: showGratitudeControl, showLayerControl: showLayerControl, donationWidget: donationWidget, showThemeControl: showThemeControl, defaultTheme: defaultTheme, children: children }) }) }));
2903
2918
  }
2904
2919
 
2905
- const goldenRatioConjugate = 0.618033988749895;
2906
- const randomColor = () => {
2907
- return hsvToHex((Math.random() + goldenRatioConjugate) % 1, 0.8, 0.7);
2908
- };
2909
- function hsvToHex(h, s, v) {
2910
- let r, g, b;
2911
- const i = Math.floor(h * 6);
2912
- const f = h * 6 - i;
2913
- const p = v * (1 - s);
2914
- const q = v * (1 - f * s);
2915
- const t = v * (1 - (1 - f) * s);
2916
- switch (i % 6) {
2917
- case 0:
2918
- r = v;
2919
- g = t;
2920
- b = p;
2921
- break;
2922
- case 1:
2923
- r = q;
2924
- g = v;
2925
- b = p;
2926
- break;
2927
- case 2:
2928
- r = p;
2929
- g = v;
2930
- b = t;
2931
- break;
2932
- case 3:
2933
- r = p;
2934
- g = q;
2935
- b = v;
2936
- break;
2937
- case 4:
2938
- r = t;
2939
- g = p;
2940
- b = v;
2941
- break;
2942
- case 5:
2943
- r = v;
2944
- g = p;
2945
- b = q;
2946
- break;
2947
- }
2948
- return rgbToHex(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255));
2949
- }
2950
- const rgbToHex = (r, g, b) => '#' +
2951
- [r, g, b]
2952
- .map((x) => {
2953
- const hex = x.toString(16);
2954
- return hex.length === 1 ? `0${hex}` : hex;
2955
- })
2956
- .join('');
2920
+ const LayerContext = React.createContext({
2921
+ name: '',
2922
+ markerDefaultColor: '',
2923
+ markerDefaultColor2: '',
2924
+ markerShape: '',
2925
+ menuText: '',
2926
+ });
2957
2927
 
2958
2928
  /**
2959
- * @category Input
2929
+ * @category Map
2960
2930
  */
2961
- function TextAreaInput({ labelTitle, dataField, labelStyle, containerStyle, inputStyle, defaultValue, placeholder, required = true, updateFormValue, }) {
2962
- const ref = React.useRef(null);
2963
- const [inputValue, setInputValue] = React.useState(defaultValue);
2931
+ const Layer = ({ data, children, name = 'places', menuIcon = 'MapPinIcon', menuText = 'add new place', menuColor = '#2E7D32', markerIcon, markerShape = 'circle', markerDefaultColor = '#777', markerDefaultColor2 = 'RGBA(35, 31, 32, 0.2)', api, itemType, userProfileLayer = false, customEditLink, customEditParameter,
2932
+ // eslint-disable-next-line camelcase
2933
+ public_edit_items, listed = true, }) => {
2934
+ const setItemsApi = useSetItemsApi();
2935
+ const setItemsData = useSetItemsData();
2936
+ const addTag = useAddTag();
2937
+ const [newTagsToAdd] = React.useState([]);
2938
+ const [tagsReady] = React.useState(false);
2964
2939
  React.useEffect(() => {
2965
- setInputValue(defaultValue);
2966
- }, [defaultValue]);
2967
- const handleChange = (e) => {
2968
- const newValue = e.target.value;
2969
- setInputValue(newValue);
2970
- if (updateFormValue) {
2971
- updateFormValue(newValue);
2940
+ data &&
2941
+ setItemsData({
2942
+ data,
2943
+ children,
2944
+ name,
2945
+ menuIcon,
2946
+ menuText,
2947
+ menuColor,
2948
+ markerIcon,
2949
+ markerShape,
2950
+ markerDefaultColor,
2951
+ markerDefaultColor2,
2952
+ api,
2953
+ itemType,
2954
+ userProfileLayer,
2955
+ // Can we just use editCallback for all cases?
2956
+ customEditLink,
2957
+ customEditParameter,
2958
+ // eslint-disable-next-line camelcase
2959
+ public_edit_items,
2960
+ listed,
2961
+ });
2962
+ api &&
2963
+ setItemsApi({
2964
+ data,
2965
+ children,
2966
+ name,
2967
+ menuIcon,
2968
+ menuText,
2969
+ menuColor,
2970
+ markerIcon,
2971
+ markerShape,
2972
+ markerDefaultColor,
2973
+ markerDefaultColor2,
2974
+ api,
2975
+ itemType,
2976
+ userProfileLayer,
2977
+ customEditLink,
2978
+ customEditParameter,
2979
+ // eslint-disable-next-line camelcase
2980
+ public_edit_items,
2981
+ listed,
2982
+ });
2983
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2984
+ }, [data, api]);
2985
+ React.useEffect(() => {
2986
+ if (tagsReady) {
2987
+ const processedTags = {};
2988
+ newTagsToAdd.map((newtag) => {
2989
+ if (!processedTags[newtag.name]) {
2990
+ processedTags[newtag.name] = true;
2991
+ addTag(newtag);
2992
+ }
2993
+ return null;
2994
+ });
2972
2995
  }
2973
- };
2974
- return (jsxRuntime.jsxs("div", { className: `tw:form-control tw:w-full ${containerStyle ?? ''}`, children: [labelTitle ? (jsxRuntime.jsx("label", { className: 'tw:label', children: jsxRuntime.jsx("span", { className: `tw:label-text tw:text-base-content ${labelStyle ?? ''}`, children: labelTitle }) })) : null, jsxRuntime.jsx("textarea", { required: required, ref: ref, value: inputValue, name: dataField, className: `tw:textarea tw:textarea-bordered tw:w-full tw:leading-5 ${inputStyle ?? ''}`, placeholder: placeholder ?? '', onChange: handleChange })] }));
2975
- }
2996
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2997
+ }, [tagsReady]);
2998
+ return (jsxRuntime.jsx(LayerContext.Provider, { value: {
2999
+ name,
3000
+ markerDefaultColor,
3001
+ markerDefaultColor2,
3002
+ markerShape,
3003
+ markerIcon,
3004
+ menuText,
3005
+ }, children: children }));
3006
+ };
2976
3007
 
2977
3008
  /**
2978
- * @category Input
3009
+ * This Components injects Tags comming from an {@link ItemsApi | `API`}
3010
+ * ```tsx
3011
+ * <Tags api={tagsApi} />
3012
+ * ```
3013
+ * or from on {@link Tag| `Array`}
3014
+ * ```tsx
3015
+ * <Tags data={tags} />
3016
+ * ```
3017
+ * Can be child of {@link AppShell | `AppShell`}
3018
+ * ```tsx
3019
+ * <AppShell>
3020
+ * ...
3021
+ * <Tags api={tagsApi} />
3022
+ * </AppShell>
3023
+ * ```
3024
+ * Or child of {@link UtopiaMap | `UtopiaMap`}
3025
+ * ```tsx
3026
+ * <UtopiaMap>
3027
+ * ...
3028
+ * <Tags api={tagsApi} />
3029
+ * </UtopiaMap>
3030
+ * ```
3031
+ * @category Map
2979
3032
  */
2980
- function TextInput({ labelTitle, labelStyle, type, dataField, containerStyle, inputStyle, defaultValue, placeholder, autocomplete, pattern, required = true, updateFormValue, }) {
2981
- const [inputValue, setInputValue] = React.useState(defaultValue ?? '');
3033
+ function Tags({ data, api }) {
3034
+ const setTagData = useSetTagData();
3035
+ const setTagApi = useSetTagApi();
2982
3036
  React.useEffect(() => {
2983
- setInputValue(defaultValue ?? '');
2984
- }, [defaultValue]);
2985
- const handleChange = (e) => {
2986
- const newValue = e.target.value;
2987
- setInputValue(newValue);
2988
- if (updateFormValue) {
2989
- updateFormValue(newValue);
2990
- }
2991
- };
2992
- return (jsxRuntime.jsxs("div", { className: `tw:form-control ${containerStyle ?? ''}`, children: [labelTitle ? (jsxRuntime.jsx("label", { className: 'tw:label', children: jsxRuntime.jsx("span", { className: `tw:label-text tw:text-base-content ${labelStyle ?? ''}`, children: labelTitle }) })) : null, jsxRuntime.jsx("input", { required: required, pattern: pattern, type: type ?? 'text', name: dataField, value: inputValue, placeholder: placeholder ?? '', autoComplete: autocomplete, onChange: handleChange, className: `tw:input tw:input-bordered tw:w-full ${inputStyle ?? ''}` })] }));
2993
- }
2994
-
2995
- function ItemFormPopup(props) {
2996
- const [spinner, setSpinner] = React.useState(false);
2997
- const [popupTitle, setPopupTitle] = React.useState('');
2998
- const formRef = React.useRef(null);
2999
- const map = reactLeaflet.useMap();
3000
- const addItem = useAddItem();
3001
- const updateItem = useUpdateItem();
3002
- const items = useItems();
3003
- useRemoveItem();
3004
- const tags = useTags();
3005
- const addTag = useAddTag();
3037
+ data && setTagData(data);
3038
+ api && setTagApi(api);
3039
+ // eslint-disable-next-line react-hooks/exhaustive-deps
3040
+ }, [api, data]);
3041
+ const location = reactRouterDom.useLocation();
3042
+ const addFilterTag = useAddFilterTag();
3006
3043
  const resetFilterTags = useResetFilterTags();
3007
- const { user } = useAuth();
3008
- const handleSubmit = async (evt) => {
3009
- const formItem = {};
3010
- Array.from(evt.target).forEach((input) => {
3011
- if (input.name) {
3012
- formItem[input.name] = input.value;
3013
- }
3014
- });
3015
- formItem.position = { type: 'Point', coordinates: [props.position.lng, props.position.lat] };
3016
- evt.preventDefault();
3017
- const name = formItem.name ? formItem.name : user?.first_name;
3018
- if (!name) {
3019
- reactToastify.toast.error('Name is must be defined');
3020
- return;
3021
- }
3022
- setSpinner(true);
3023
- formItem.text &&
3024
- formItem.text
3025
- .toLocaleLowerCase()
3026
- .match(hashTagRegex)
3027
- ?.map((tag) => {
3028
- if (!tags.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) {
3029
- addTag({ id: crypto.randomUUID(), name: tag.slice(1), color: randomColor() });
3030
- }
3031
- return null;
3032
- });
3033
- if (props.item) {
3034
- let success = false;
3035
- try {
3036
- await props.layer.api?.updateItem({ ...formItem, id: props.item.id });
3037
- success = true;
3038
- // eslint-disable-next-line no-catch-all/no-catch-all
3039
- }
3040
- catch (error) {
3041
- reactToastify.toast.error(error.toString());
3042
- }
3043
- if (success) {
3044
- updateItem({ ...props.item, ...formItem });
3045
- reactToastify.toast.success('Item updated');
3046
- }
3047
- setSpinner(false);
3048
- map.closePopup();
3049
- }
3050
- else {
3051
- const item = items.find((i) => i.user_created?.id === user?.id && i.layer === props.layer);
3052
- const uuid = crypto.randomUUID();
3053
- let success = false;
3054
- try {
3055
- props.layer.userProfileLayer &&
3056
- item &&
3057
- (await props.layer.api?.updateItem({ ...formItem, id: item.id }));
3058
- (!props.layer.userProfileLayer || !item) &&
3059
- (await props.layer.api?.createItem({
3060
- ...formItem,
3061
- name,
3062
- id: uuid,
3063
- }));
3064
- success = true;
3065
- // eslint-disable-next-line no-catch-all/no-catch-all
3066
- }
3067
- catch (error) {
3068
- reactToastify.toast.error(error.toString());
3069
- }
3070
- if (success) {
3071
- if (props.layer.userProfileLayer && item)
3072
- updateItem({ ...item, ...formItem });
3073
- if (!props.layer.userProfileLayer || !item) {
3074
- addItem({
3075
- ...formItem,
3076
- name: (formItem.name ? formItem.name : user?.first_name) ?? '',
3077
- user_created: user ?? undefined,
3078
- id: uuid,
3079
- layer: props.layer,
3080
- public_edit: !user,
3081
- });
3082
- }
3083
- reactToastify.toast.success('New item created');
3084
- resetFilterTags();
3085
- }
3086
- setSpinner(false);
3087
- map.closePopup();
3088
- }
3089
- props.setItemFormPopup(null);
3090
- };
3091
- const resetPopup = () => {
3092
- if (formRef.current) {
3093
- formRef.current.reset();
3094
- }
3095
- };
3096
- React.useEffect(() => {
3097
- resetPopup();
3098
- }, [props.position]);
3099
- return (jsxRuntime.jsx(reactLeaflet.Popup, { minWidth: 275, maxWidth: 275, autoPanPadding: [20, 80], eventHandlers: {
3100
- remove: () => {
3101
- setTimeout(function () {
3102
- resetPopup();
3103
- }, 100);
3104
- },
3105
- }, position: props.position, children: jsxRuntime.jsxs("form", { ref: formRef, onReset: resetPopup, autoComplete: 'off', onSubmit: (e) => handleSubmit(e), children: [props.item ? (jsxRuntime.jsx("div", { className: 'tw:h-3' })) : (jsxRuntime.jsx("div", { className: 'tw:flex tw:justify-center', children: jsxRuntime.jsx("b", { className: 'tw:text-xl tw:text-center tw:font-bold', children: props.layer.menuText }) })), props.children ? (React.Children.toArray(props.children).map((child) => React.isValidElement(child)
3106
- ? React.cloneElement(child, {
3107
- item: props.item,
3108
- key: props.position.toString(),
3109
- setPopupTitle,
3110
- })
3111
- : '')) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(TextInput, { type: 'text', placeholder: 'Name', dataField: 'name', defaultValue: props.item ? props.item.name : '', inputStyle: '' }), jsxRuntime.jsx(TextAreaInput, { placeholder: 'Text', dataField: 'text', defaultValue: props.item?.text ?? '', inputStyle: 'tw:h-40 tw:mt-5' }, props.position.toString())] })), jsxRuntime.jsx("div", { className: 'tw:flex tw:justify-center', children: jsxRuntime.jsx("button", { className: spinner
3112
- ? 'tw:btn tw:btn-disabled tw:mt-5 tw:place-self-center'
3113
- : 'tw:btn tw:mt-5 tw:place-self-center', type: 'submit', children: spinner ? jsxRuntime.jsx("span", { className: 'tw:loading tw:loading-spinner' }) : 'Save' }) })] }) }));
3114
- }
3115
-
3116
- // in miliseconds
3117
- const units = [
3118
- { label: 'year', seconds: 31536000 },
3119
- { label: 'month', seconds: 2592000 },
3120
- { label: 'week', seconds: 604800 },
3121
- { label: 'day', seconds: 86400 },
3122
- { label: 'hour', seconds: 3600 },
3123
- { label: 'minute', seconds: 60 },
3124
- { label: 'second', seconds: 1 },
3125
- ];
3126
- const timeAgo = (date) => {
3127
- const time = Math.floor((new Date().valueOf() - new Date(date).valueOf()) / 1000);
3128
- const { interval, unit } = calculateTimeDifference(time);
3129
- const suffix = interval === 1 ? '' : 's';
3130
- return `${interval} ${unit}${suffix} ago`;
3131
- };
3132
- const calculateTimeDifference = (time) => {
3133
- for (const { label, seconds } of units) {
3134
- const interval = Math.floor(time / seconds);
3135
- if (interval >= 1) {
3136
- return {
3137
- interval,
3138
- unit: label,
3139
- };
3140
- }
3141
- }
3142
- return {
3143
- interval: 0,
3144
- unit: '',
3145
- };
3146
- };
3147
-
3148
- function EllipsisVerticalIcon({
3149
- title,
3150
- titleId,
3151
- ...props
3152
- }, svgRef) {
3153
- return /*#__PURE__*/React__namespace.createElement("svg", Object.assign({
3154
- xmlns: "http://www.w3.org/2000/svg",
3155
- viewBox: "0 0 16 16",
3156
- fill: "currentColor",
3157
- "aria-hidden": "true",
3158
- "data-slot": "icon",
3159
- ref: svgRef,
3160
- "aria-labelledby": titleId
3161
- }, props), title ? /*#__PURE__*/React__namespace.createElement("title", {
3162
- id: titleId
3163
- }, title) : null, /*#__PURE__*/React__namespace.createElement("path", {
3164
- d: "M8 2a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM8 6.5a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM9.5 12.5a1.5 1.5 0 1 0-3 0 1.5 1.5 0 0 0 3 0Z"
3165
- }));
3166
- }
3167
- const ForwardRef$9 = /*#__PURE__*/ React__namespace.forwardRef(EllipsisVerticalIcon);
3168
-
3169
- function PencilIcon({
3170
- title,
3171
- titleId,
3172
- ...props
3173
- }, svgRef) {
3174
- return /*#__PURE__*/React__namespace.createElement("svg", Object.assign({
3175
- xmlns: "http://www.w3.org/2000/svg",
3176
- viewBox: "0 0 24 24",
3177
- fill: "currentColor",
3178
- "aria-hidden": "true",
3179
- "data-slot": "icon",
3180
- ref: svgRef,
3181
- "aria-labelledby": titleId
3182
- }, props), title ? /*#__PURE__*/React__namespace.createElement("title", {
3183
- id: titleId
3184
- }, title) : null, /*#__PURE__*/React__namespace.createElement("path", {
3185
- d: "M21.731 2.269a2.625 2.625 0 0 0-3.712 0l-1.157 1.157 3.712 3.712 1.157-1.157a2.625 2.625 0 0 0 0-3.712ZM19.513 8.199l-3.712-3.712-12.15 12.15a5.25 5.25 0 0 0-1.32 2.214l-.8 2.685a.75.75 0 0 0 .933.933l2.685-.8a5.25 5.25 0 0 0 2.214-1.32L19.513 8.2Z"
3186
- }));
3187
- }
3188
- const ForwardRef$8 = /*#__PURE__*/ React__namespace.forwardRef(PencilIcon);
3189
-
3190
- function TrashIcon({
3191
- title,
3192
- titleId,
3193
- ...props
3194
- }, svgRef) {
3195
- return /*#__PURE__*/React__namespace.createElement("svg", Object.assign({
3196
- xmlns: "http://www.w3.org/2000/svg",
3197
- viewBox: "0 0 24 24",
3198
- fill: "currentColor",
3199
- "aria-hidden": "true",
3200
- "data-slot": "icon",
3201
- ref: svgRef,
3202
- "aria-labelledby": titleId
3203
- }, props), title ? /*#__PURE__*/React__namespace.createElement("title", {
3204
- id: titleId
3205
- }, title) : null, /*#__PURE__*/React__namespace.createElement("path", {
3206
- fillRule: "evenodd",
3207
- d: "M16.5 4.478v.227a48.816 48.816 0 0 1 3.878.512.75.75 0 1 1-.256 1.478l-.209-.035-1.005 13.07a3 3 0 0 1-2.991 2.77H8.084a3 3 0 0 1-2.991-2.77L4.087 6.66l-.209.035a.75.75 0 0 1-.256-1.478A48.567 48.567 0 0 1 7.5 4.705v-.227c0-1.564 1.213-2.9 2.816-2.951a52.662 52.662 0 0 1 3.369 0c1.603.051 2.815 1.387 2.815 2.951Zm-6.136-1.452a51.196 51.196 0 0 1 3.273 0C14.39 3.05 15 3.684 15 4.478v.113a49.488 49.488 0 0 0-6 0v-.113c0-.794.609-1.428 1.364-1.452Zm-.355 5.945a.75.75 0 1 0-1.5.058l.347 9a.75.75 0 1 0 1.499-.058l-.346-9Zm5.48.058a.75.75 0 1 0-1.498-.058l-.347 9a.75.75 0 0 0 1.5.058l.345-9Z",
3208
- clipRule: "evenodd"
3209
- }));
3210
- }
3211
- const ForwardRef$7 = /*#__PURE__*/ React__namespace.forwardRef(TrashIcon);
3212
-
3213
- var TargetDotSVG = 'data:image/svg+xml;base64,PHN2ZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Ryb2tlPSdjdXJyZW50Q29sb3InCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsPSdjdXJyZW50Q29sb3InCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJva2VXaWR0aD0nMCcKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXdCb3g9JzAgMCA1MTIgNTEyJwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPSd3LTUgaC01JwogICAgICAgICAgICAgICAgICAgICAgICAgICAgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJwogICAgICAgICAgICAgICAgICAgICAgICAgID4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9J00yNTYgMGMxNy43IDAgMzIgMTQuMyAzMiAzMlY0Mi40YzkzLjcgMTMuOSAxNjcuNyA4OCAxODEuNiAxODEuNkg0ODBjMTcuNyAwIDMyIDE0LjMgMzIgMzJzLTE0LjMgMzItMzIgMzJINDY5LjZjLTEzLjkgOTMuNy04OCAxNjcuNy0xODEuNiAxODEuNlY0ODBjMCAxNy43LTE0LjMgMzItMzIgMzJzLTMyLTE0LjMtMzItMzJWNDY5LjZDMTMwLjMgNDU1LjcgNTYuMyAzODEuNyA0Mi40IDI4OEgzMmMtMTcuNyAwLTMyLTE0LjMtMzItMzJzMTQuMy0zMiAzMi0zMkg0Mi40QzU2LjMgMTMwLjMgMTMwLjMgNTYuMyAyMjQgNDIuNFYzMmMwLTE3LjcgMTQuMy0zMiAzMi0zMnpNMTA3LjQgMjg4YzEyLjUgNTguMyA1OC40IDEwNC4xIDExNi42IDExNi42VjM4NGMwLTE3LjcgMTQuMy0zMiAzMi0zMnMzMiAxNC4zIDMyIDMydjIwLjZjNTguMy0xMi41IDEwNC4xLTU4LjQgMTE2LjYtMTE2LjZIMzg0Yy0xNy43IDAtMzItMTQuMy0zMi0zMnMxNC4zLTMyIDMyLTMyaDIwLjZDMzkyLjEgMTY1LjcgMzQ2LjMgMTE5LjkgMjg4IDEwNy40VjEyOGMwIDE3LjctMTQuMyAzMi0zMiAzMnMtMzItMTQuMy0zMi0zMlYxMDcuNEMxNjUuNyAxMTkuOSAxMTkuOSAxNjUuNyAxMDcuNCAyMjRIMTI4YzE3LjcgMCAzMiAxNC4zIDMyIDMycy0xNC4zIDMyLTMyIDMySDEwNy40ek0yNTYgMjI0YTMyIDMyIDAgMSAxIDAgNjQgMzIgMzIgMCAxIDEgMC02NHonPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICAgICAgICA8L3N2Zz4=';
3214
-
3215
- const isClickInsideRectangle = (e, element) => {
3216
- const r = element.getBoundingClientRect();
3217
- return e.clientX > r.left && e.clientX < r.right && e.clientY > r.top && e.clientY < r.bottom;
3218
- };
3219
- const DialogModal = ({ title, isOpened, onClose, children, showCloseButton = true, closeOnClickOutside = true, className, }) => {
3220
- const ref = React.useRef(null);
3221
- React.useEffect(() => {
3222
- if (isOpened) {
3223
- ref.current?.showModal();
3224
- ref.current?.classList.remove('tw:hidden');
3225
- document.body.classList.add('modal-open'); // prevent bg scroll
3226
- }
3227
- else {
3228
- ref.current?.close();
3229
- ref.current?.classList.add('tw:hidden');
3230
- document.body.classList.remove('modal-open');
3231
- }
3232
- }, [isOpened]);
3233
- if (isOpened) {
3234
- return (jsxRuntime.jsx("dialog", { className: `${className ?? ''} card tw:shadow-xl tw:absolute tw:right-0 tw:top-0 tw:bottom-0 tw:left-0 tw:m-auto tw:transition-opacity tw:duration-300 tw:p-4 tw:max-w-xl tw:bg-base-100`, ref: ref, onCancel: onClose, onClick: (e) => ref.current && !isClickInsideRectangle(e, ref.current) && closeOnClickOutside && onClose(), children: jsxRuntime.jsxs("div", { className: 'card-body tw:p-2', children: [jsxRuntime.jsx("h2", { className: 'tw:text-2xl tw:font-semibold tw:mb-2 tw:text-center', children: title }), children, showCloseButton && (jsxRuntime.jsx("button", { className: 'btn btn-sm btn-circle btn-ghost tw:absolute tw:right-2 tw:top-2', onClick: onClose, children: "\u2715" }))] }) }));
3235
- }
3236
- else
3237
- return jsxRuntime.jsx(jsxRuntime.Fragment, {});
3238
- };
3239
-
3240
- function HeaderView({ item, api, editCallback, deleteCallback, setPositionCallback, loading, hideMenu = false, big = false, truncateSubname = true, hideSubname = false, showAddress = false, }) {
3241
- const [modalOpen, setModalOpen] = React.useState(false);
3242
- const hasUserPermission = useHasUserPermission();
3243
- const navigate = reactRouterDom.useNavigate();
3244
- const appState = useAppState();
3245
- const [imageLoaded, setImageLoaded] = React.useState(false);
3246
- const avatar = item.image && appState.assetsApi.url + item.image + '?width=160&heigth=160';
3247
- const title = item.name;
3248
- const subtitle = item.subname;
3249
- const [address] = React.useState('');
3250
- const params = new URLSearchParams(window.location.search);
3251
- const openDeleteModal = async (event) => {
3252
- setModalOpen(true);
3253
- event.stopPropagation();
3254
- };
3255
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: 'tw:flex tw:flex-row', children: [jsxRuntime.jsx("div", { className: 'tw:grow tw:max-w-[calc(100%-60px)] }', children: jsxRuntime.jsxs("div", { className: 'flex items-center', children: [avatar && (jsxRuntime.jsx("div", { className: 'tw:avatar', children: jsxRuntime.jsxs("div", { className: `${big ? 'tw:w-20' : 'tw:w-10'} tw:inline tw:items-center tw:justify-center overflow-hidden`, children: [jsxRuntime.jsx("img", { className: 'tw:w-full tw:h-full tw:object-cover tw:rounded-full', src: avatar, alt: item.name + ' logo', onLoad: () => setImageLoaded(true), onError: () => setImageLoaded(false), style: { display: imageLoaded ? 'block' : 'none' } }), !imageLoaded && (jsxRuntime.jsx("div", { className: 'tw:w-full tw:h-full tw:bg-gray-200 tw:rounded-full' }))] }) })), jsxRuntime.jsxs("div", { className: `${avatar ? 'tw:ml-2' : ''} tw:overflow-hidden`, children: [jsxRuntime.jsx("div", { className: `${big ? 'tw:xl:text-3xl tw:text-2xl' : 'tw:text-xl'} tw:font-semibold tw:truncate`, title: title, children: title }), showAddress && address && !hideSubname && (jsxRuntime.jsx("div", { className: `tw:text-xs tw:text-gray-500 ${truncateSubname && 'tw:truncate'}`, children: address })), subtitle && !hideSubname && (jsxRuntime.jsx("div", { className: `tw:text-xs tw:opacity-50 ${truncateSubname && 'tw:truncate'}`, children: subtitle }))] })] }) }), jsxRuntime.jsx("div", { onClick: (e) => e.stopPropagation(), className: `${big ? 'tw:mt-5' : 'tw:mt-1'}`, children: (api?.deleteItem || item.layer?.api?.updateItem) &&
3256
- (hasUserPermission(api?.collectionName, 'delete', item) ||
3257
- hasUserPermission(api?.collectionName, 'update', item)) &&
3258
- !hideMenu && (jsxRuntime.jsxs("div", { className: 'tw:dropdown tw:dropdown-bottom', children: [jsxRuntime.jsx("label", { tabIndex: 0, className: 'tw:bg-base-100 tw:btn tw:m-1 tw:leading-3 tw:border-none tw:min-h-0 tw:h-6', children: jsxRuntime.jsx(ForwardRef$9, { className: 'tw:h-5 tw:w-5' }) }), jsxRuntime.jsxs("ul", { tabIndex: 0, className: 'tw:dropdown-content tw:menu tw:p-2 tw:shadow tw:bg-base-100 tw:rounded-box tw:z-1000', children: [api?.updateItem &&
3259
- hasUserPermission(api.collectionName, 'update', item) &&
3260
- editCallback && (jsxRuntime.jsx("li", { children: jsxRuntime.jsx("a", { className: 'tw:text-base-content! tw:cursor-pointer', onClick: (e) => item.layer?.customEditLink
3261
- ? navigate(`${item.layer.customEditLink}${item.layer.customEditParameter ? `/${item.id}${params && '?' + params}` : ''} `)
3262
- : editCallback(e), children: jsxRuntime.jsx(ForwardRef$8, { className: 'tw:h-5 tw:w-5' }) }) })), api?.updateItem &&
3263
- hasUserPermission(api.collectionName, 'update', item) &&
3264
- setPositionCallback && (jsxRuntime.jsx("li", { children: jsxRuntime.jsx("a", { className: 'tw:text-base-content! tw:cursor-pointer', onClick: setPositionCallback, children: jsxRuntime.jsx(SVG, { src: TargetDotSVG, className: 'tw:w-5 tw:h-5' }) }) })), api?.deleteItem &&
3265
- hasUserPermission(api.collectionName, 'delete', item) &&
3266
- deleteCallback && (jsxRuntime.jsx("li", { children: jsxRuntime.jsx("a", { className: 'tw:cursor-pointer tw:text-error!', onClick: openDeleteModal, children: loading ? (jsxRuntime.jsx("span", { className: 'tw:loading tw:loading-spinner tw:loading-sm' })) : (jsxRuntime.jsx(ForwardRef$7, { className: 'tw:h-5 tw:w-5' })) }) }))] })] })) })] }), jsxRuntime.jsx(DialogModal, { isOpened: modalOpen, title: 'Are you sure?', showCloseButton: false, onClose: () => setModalOpen(false), children: jsxRuntime.jsxs("div", { onClick: (e) => e.stopPropagation(), children: [jsxRuntime.jsxs("span", { children: ["Do you want to delete ", jsxRuntime.jsx("b", { children: item.name }), "?"] }), jsxRuntime.jsx("div", { className: 'tw:grid', children: jsxRuntime.jsxs("div", { className: 'tw:flex tw:justify-between', children: [jsxRuntime.jsx("label", { className: 'tw:btn tw:mt-4 tw:btn-error', onClick: (e) => {
3267
- deleteCallback(e);
3268
- setModalOpen(false);
3269
- }, children: "Yes" }), jsxRuntime.jsx("label", { className: 'tw:btn tw:mt-4', onClick: () => setModalOpen(false), children: "No" })] }) })] }) })] }));
3270
- }
3271
-
3272
- // eslint-disable-next-line react/display-name
3273
- const ItemViewPopup = React.forwardRef((props, ref) => {
3274
- const map = reactLeaflet.useMap();
3275
- const [loading, setLoading] = React.useState(false);
3276
- const removeItem = useRemoveItem();
3277
- const updadateItem = useUpdateItem();
3278
- const navigate = reactRouterDom.useNavigate();
3279
- const setSelectPosition = useSetSelectPosition();
3280
- const [infoExpanded, setInfoExpanded] = React.useState(false);
3281
- const handleEdit = (event) => {
3282
- event.stopPropagation();
3283
- map.closePopup();
3284
- props.setItemFormPopup &&
3285
- props.setItemFormPopup({
3286
- position: new leaflet.LatLng(props.item.position?.coordinates[1], props.item.position?.coordinates[0]),
3287
- layer: props.item.layer,
3288
- item: props.item,
3289
- setItemFormPopup: props.setItemFormPopup,
3290
- });
3291
- };
3292
- const handleDelete = async (event) => {
3293
- event.stopPropagation();
3294
- setLoading(true);
3295
- let success = false;
3296
- try {
3297
- !props.item.layer?.userProfileLayer &&
3298
- (await props.item.layer?.api?.deleteItem(props.item.id));
3299
- props.item.layer?.userProfileLayer &&
3300
- (await props.item.layer.api?.updateItem({ id: props.item.id, position: null }));
3301
- success = true;
3302
- // eslint-disable-next-line no-catch-all/no-catch-all
3303
- }
3304
- catch (error) {
3305
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
3306
- reactToastify.toast.error(error.toString());
3307
- }
3308
- if (success) {
3309
- !props.item.layer?.userProfileLayer && removeItem(props.item);
3310
- props.item.layer?.userProfileLayer && updadateItem({ ...props.item, position: undefined });
3311
- reactToastify.toast.success('Item deleted');
3312
- }
3313
- setLoading(false);
3314
- map.closePopup();
3315
- const params = new URLSearchParams(window.location.search);
3316
- window.history.pushState({}, '', '/' + `${params ? `?${params}` : ''}`);
3317
- navigate('/');
3318
- };
3319
- return (jsxRuntime.jsx(reactLeaflet.Popup, { ref: ref, maxHeight: 377, minWidth: 275, maxWidth: 275, autoPanPadding: [20, 80], children: jsxRuntime.jsxs("div", { className: 'tw:bg-base-100 tw:text-base-content', children: [jsxRuntime.jsx(HeaderView, { api: props.item.layer?.api, item: props.item, editCallback: handleEdit, deleteCallback: handleDelete, setPositionCallback: () => {
3320
- map.closePopup();
3321
- setSelectPosition(props.item);
3322
- navigate('/');
3323
- }, loading: loading }), jsxRuntime.jsx("div", { className: 'tw:overflow-y-auto tw:overflow-x-hidden tw:max-h-64 fade', children: props.children ? (React.Children.toArray(props.children).map((child) => React.isValidElement(child)
3324
- ? React.cloneElement(child, { item: props.item })
3325
- : '')) : (jsxRuntime.jsx(TextView, { text: props.item.text, itemId: props.item.id })) }), jsxRuntime.jsxs("div", { className: 'tw:flex tw:-mb-1 tw:flex-row tw:mr-2 tw:mt-1', children: [infoExpanded ? (jsxRuntime.jsx("p", { className: 'tw:italic tw:min-h-[21px] tw:my-0! tw:opacity-50', children: `${props.item.date_updated && props.item.date_updated !== props.item.date_created ? 'updated' : 'posted'} ${props.item && props.item.user_created && props.item.user_created.first_name ? `by ${props.item.user_created.first_name}` : ''} ${props.item.date_updated ? timeAgo(props.item.date_updated) : timeAgo(props.item.date_created)}` })) : (jsxRuntime.jsx("p", { className: 'tw:my-0! tw:min-h-[21px] tw:font-bold tw:cursor-pointer tw:text-gray-500', onClick: () => setInfoExpanded(true), children: "\u24D8" })), jsxRuntime.jsx("div", { className: 'tw:grow' })] })] }) }));
3326
- });
3327
-
3328
- /**
3329
- * @category Map
3330
- */
3331
- const Layer = ({ data, children, name = 'places', menuIcon = 'MapPinIcon', menuText = 'add new place', menuColor = '#2E7D32', markerIcon, markerShape = 'circle', markerDefaultColor = '#777', markerDefaultColor2 = 'RGBA(35, 31, 32, 0.2)', api, itemType, userProfileLayer = false, customEditLink, customEditParameter,
3332
- // eslint-disable-next-line camelcase
3333
- public_edit_items, listed = true, setItemFormPopup, itemFormPopup, clusterRef, }) => {
3334
- const filterTags = useFilterTags();
3335
- const items = useItems();
3336
- const setItemsApi = useSetItemsApi();
3337
- const setItemsData = useSetItemsData();
3338
- const getItemTags = useGetItemTags();
3339
- const addMarker = useAddMarker();
3340
- const addPopup = useAddPopup();
3341
- const leafletRefs = useLeafletRefs();
3342
- const allTagsLoaded = useAllTagsLoaded();
3343
- const allItemsLoaded = useAllItemsLoaded();
3344
- const setMarkerClicked = useSetMarkerClicked();
3345
- const selectPosition = useSelectPosition();
3346
- const tags = useTags();
3347
- const addTag = useAddTag();
3348
- const [newTagsToAdd, setNewTagsToAdd] = React.useState([]);
3349
- const [tagsReady, setTagsReady] = React.useState(false);
3350
- const isLayerVisible = useIsLayerVisible();
3351
- const isGroupTypeVisible = useIsGroupTypeVisible();
3352
- const visibleGroupTypes = useVisibleGroupType();
3353
- const appState = useAppState();
3354
- React.useEffect(() => {
3355
- data &&
3356
- setItemsData({
3357
- data,
3358
- children,
3359
- name,
3360
- menuIcon,
3361
- menuText,
3362
- menuColor,
3363
- markerIcon,
3364
- markerShape,
3365
- markerDefaultColor,
3366
- markerDefaultColor2,
3367
- api,
3368
- itemType,
3369
- userProfileLayer,
3370
- // Can we just use editCallback for all cases?
3371
- customEditLink,
3372
- customEditParameter,
3373
- // eslint-disable-next-line camelcase
3374
- public_edit_items,
3375
- listed,
3376
- setItemFormPopup,
3377
- itemFormPopup,
3378
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
3379
- clusterRef,
3380
- });
3381
- api &&
3382
- setItemsApi({
3383
- data,
3384
- children,
3385
- name,
3386
- menuIcon,
3387
- menuText,
3388
- menuColor,
3389
- markerIcon,
3390
- markerShape,
3391
- markerDefaultColor,
3392
- markerDefaultColor2,
3393
- api,
3394
- itemType,
3395
- userProfileLayer,
3396
- customEditLink,
3397
- customEditParameter,
3398
- // eslint-disable-next-line camelcase
3399
- public_edit_items,
3400
- listed,
3401
- setItemFormPopup,
3402
- itemFormPopup,
3403
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
3404
- clusterRef,
3405
- });
3406
- // eslint-disable-next-line react-hooks/exhaustive-deps
3407
- }, [data, api]);
3408
- React.useEffect(() => {
3409
- if (tagsReady) {
3410
- const processedTags = {};
3411
- newTagsToAdd.map((newtag) => {
3412
- if (!processedTags[newtag.name]) {
3413
- processedTags[newtag.name] = true;
3414
- addTag(newtag);
3415
- }
3416
- return null;
3417
- });
3418
- }
3419
- // eslint-disable-next-line react-hooks/exhaustive-deps
3420
- }, [tagsReady]);
3421
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [items &&
3422
- items
3423
- .filter((item) => item.layer?.name === name)
3424
- .filter((item) => filterTags.length === 0
3425
- ? item
3426
- : filterTags.some((tag) => getItemTags(item).some((filterTag) => filterTag.name.toLocaleLowerCase() === tag.name.toLocaleLowerCase())))
3427
- .filter((item) => item.layer && isLayerVisible(item.layer))
3428
- .filter((item) => (item.group_type && isGroupTypeVisible(item.group_type)) ||
3429
- visibleGroupTypes.length === 0)
3430
- .map((item) => {
3431
- if (item.position?.coordinates[0] && item.position?.coordinates[1]) {
3432
- if (item.tags) {
3433
- item.text += '\n\n';
3434
- item.tags.map((tag) => {
3435
- if (!item.text?.includes(`#${encodeTag(tag)}`)) {
3436
- item.text += `#${encodeTag(tag)}`;
3437
- }
3438
- return item.text;
3439
- });
3440
- }
3441
- if (allTagsLoaded && allItemsLoaded) {
3442
- item.text?.match(hashTagRegex)?.map((tag) => {
3443
- if (!tags.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase()) &&
3444
- !newTagsToAdd.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) {
3445
- const newTag = {
3446
- id: crypto.randomUUID(),
3447
- name: tag.slice(1),
3448
- color: randomColor(),
3449
- };
3450
- setNewTagsToAdd((current) => [...current, newTag]);
3451
- }
3452
- return null;
3453
- });
3454
- !tagsReady && setTagsReady(true);
3455
- }
3456
- const itemTags = getItemTags(item);
3457
- const latitude = item.position.coordinates[1];
3458
- const longitude = item.position.coordinates[0];
3459
- let color1 = markerDefaultColor;
3460
- let color2 = markerDefaultColor2;
3461
- if (item.color) {
3462
- color1 = item.color;
3463
- }
3464
- else if (itemTags[0]) {
3465
- color1 = itemTags[0].color;
3466
- }
3467
- if (itemTags[0] && item.color) {
3468
- color2 = itemTags[0].color;
3469
- }
3470
- else if (itemTags[1]) {
3471
- color2 = itemTags[1].color;
3472
- }
3473
- return (jsxRuntime.jsxs(reactLeaflet.Marker, { ref: (r) => {
3474
- if (!(item.id in leafletRefs && leafletRefs[item.id].marker === r)) {
3475
- r && addMarker(item, r);
3476
- }
3477
- }, eventHandlers: {
3478
- click: () => {
3479
- selectPosition && setMarkerClicked(item);
3480
- },
3481
- }, icon: MarkerIconFactory(markerShape, color1, color2, item.markerIcon ? item.markerIcon : markerIcon, appState.assetsApi.url), position: [latitude, longitude], children: [children &&
3482
- React.Children.toArray(children).some((child) => isComponentWithType(child) && child.type.__TYPE === 'ItemView') ? (React.Children.toArray(children).map((child) => isComponentWithType(child) && child.type.__TYPE === 'ItemView' ? (jsxRuntime.jsx(ItemViewPopup, { ref: (r) => {
3483
- if (!(item.id in leafletRefs && leafletRefs[item.id].popup === r)) {
3484
- r && addPopup(item, r);
3485
- }
3486
- }, item: item, setItemFormPopup: setItemFormPopup, children: child }, item.id + item.name)) : null)) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(ItemViewPopup, { ref: (r) => {
3487
- if (!(item.id in leafletRefs && leafletRefs[item.id].popup === r)) {
3488
- r && addPopup(item, r);
3489
- }
3490
- }, item: item, setItemFormPopup: setItemFormPopup }, item.id + item.name) })), jsxRuntime.jsx(reactLeaflet.Tooltip, { offset: [0, -38], direction: 'top', children: item.name })] }, item.id));
3491
- }
3492
- else
3493
- return null;
3494
- }), itemFormPopup &&
3495
- itemFormPopup.layer.name === name &&
3496
- (children &&
3497
- React.Children.toArray(children).some((child) => isComponentWithType(child) && child.type.__TYPE === 'ItemForm') ? (React.Children.toArray(children).map((child) => isComponentWithType(child) && child.type.__TYPE === 'ItemForm' ? (jsxRuntime.jsx(ItemFormPopup, { position: itemFormPopup.position, layer: itemFormPopup.layer, setItemFormPopup: setItemFormPopup, item: itemFormPopup.item, children: child }, setItemFormPopup?.name)) : (''))) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(ItemFormPopup, { position: itemFormPopup.position, layer: itemFormPopup.layer, setItemFormPopup: setItemFormPopup, item: itemFormPopup.item }) })))] }));
3498
- };
3499
- function isComponentWithType(node) {
3500
- return React.isValidElement(node) && typeof node.type !== 'string' && '__TYPE' in node.type;
3501
- }
3502
-
3503
- /**
3504
- * This Components injects Tags comming from an {@link ItemsApi | `API`}
3505
- * ```tsx
3506
- * <Tags api={tagsApi} />
3507
- * ```
3508
- * or from on {@link Tag| `Array`}
3509
- * ```tsx
3510
- * <Tags data={tags} />
3511
- * ```
3512
- * Can be child of {@link AppShell | `AppShell`}
3513
- * ```tsx
3514
- * <AppShell>
3515
- * ...
3516
- * <Tags api={tagsApi} />
3517
- * </AppShell>
3518
- * ```
3519
- * Or child of {@link UtopiaMap | `UtopiaMap`}
3520
- * ```tsx
3521
- * <UtopiaMap>
3522
- * ...
3523
- * <Tags api={tagsApi} />
3524
- * </UtopiaMap>
3525
- * ```
3526
- * @category Map
3527
- */
3528
- function Tags({ data, api }) {
3529
- const setTagData = useSetTagData();
3530
- const setTagApi = useSetTagApi();
3531
- React.useEffect(() => {
3532
- data && setTagData(data);
3533
- api && setTagApi(api);
3534
- // eslint-disable-next-line react-hooks/exhaustive-deps
3535
- }, [api, data]);
3536
- const location = reactRouterDom.useLocation();
3537
- const addFilterTag = useAddFilterTag();
3538
- const resetFilterTags = useResetFilterTags();
3539
- const tags = useTags();
3540
- const filterTags = useFilterTags();
3541
- React.useEffect(() => {
3542
- const params = new URLSearchParams(location.search);
3543
- const urlTags = params.get('tags');
3544
- const decodedTags = urlTags ? decodeURIComponent(urlTags) : '';
3545
- const decodedTagsArray = decodedTags.split(';');
3546
- if (decodedTagsArray.some((ut) => !filterTags.find((ft) => ut.toLocaleLowerCase() === ft.name.toLocaleLowerCase())) ||
3547
- filterTags.some((ft) => !decodedTagsArray.find((ut) => ut.toLocaleLowerCase() === ft.name.toLocaleLowerCase()))) {
3548
- resetFilterTags();
3549
- decodedTagsArray.map((urlTag) => {
3550
- const tag = tags.find((t) => t.name.toLocaleLowerCase() === urlTag.toLocaleLowerCase());
3551
- tag && addFilterTag(tag);
3044
+ const tags = useTags();
3045
+ const filterTags = useFilterTags();
3046
+ React.useEffect(() => {
3047
+ const params = new URLSearchParams(location.search);
3048
+ const urlTags = params.get('tags');
3049
+ const decodedTags = urlTags ? decodeURIComponent(urlTags) : '';
3050
+ const decodedTagsArray = decodedTags.split(';');
3051
+ if (decodedTagsArray.some((ut) => !filterTags.find((ft) => ut.toLocaleLowerCase() === ft.name.toLocaleLowerCase())) ||
3052
+ filterTags.some((ft) => !decodedTagsArray.find((ut) => ut.toLocaleLowerCase() === ft.name.toLocaleLowerCase()))) {
3053
+ resetFilterTags();
3054
+ decodedTagsArray.map((urlTag) => {
3055
+ const tag = tags.find((t) => t.name.toLocaleLowerCase() === urlTag.toLocaleLowerCase());
3056
+ tag && addFilterTag(tag);
3552
3057
  return null;
3553
3058
  });
3554
3059
  }
@@ -3588,110 +3093,13 @@ function Permissions({ data, api, adminRole, }) {
3588
3093
  const setAdminRole = useSetAdminRole();
3589
3094
  const { user } = useAuth();
3590
3095
  React.useEffect(() => {
3591
- adminRole && setAdminRole(adminRole);
3592
- data && setPermissionData(data);
3593
- api && setPermissionApi(api);
3594
- // eslint-disable-next-line react-hooks/exhaustive-deps
3595
- }, [api, data, adminRole, user]);
3596
- return jsxRuntime.jsx(jsxRuntime.Fragment, {});
3597
- }
3598
-
3599
- /**
3600
- * @category Map
3601
- */
3602
- const ItemForm = ({ children, item, title, setPopupTitle, }) => {
3603
- React.useEffect(() => {
3604
- setPopupTitle && title && setPopupTitle(title);
3605
- // eslint-disable-next-line react-hooks/exhaustive-deps
3606
- }, [title]);
3607
- return (jsxRuntime.jsx("div", { children: children
3608
- ? React.Children.toArray(children).map((child) => React.isValidElement(child)
3609
- ? React.cloneElement(child, { item, test: 'test' })
3610
- : '')
3611
- : '' }));
3612
- };
3613
- ItemForm.__TYPE = 'ItemForm';
3614
-
3615
- /**
3616
- * @category Map
3617
- */
3618
- const ItemView = ({ children, item }) => {
3619
- return (jsxRuntime.jsx("div", { children: children
3620
- ? React.Children.toArray(children).map((child) => React.isValidElement(child) ? React.cloneElement(child, { item }) : null)
3621
- : null }));
3622
- };
3623
- ItemView.__TYPE = 'ItemView';
3624
-
3625
- /**
3626
- * @category Map
3627
- */
3628
- const PopupTextAreaInput = ({ dataField, placeholder, style, item, }) => {
3629
- return (jsxRuntime.jsx(TextAreaInput, { defaultValue: item?.text ? item.text : '', dataField: dataField, placeholder: placeholder, inputStyle: style }));
3630
- };
3631
-
3632
- /**
3633
- * @category Map
3634
- */
3635
- const PopupStartEndInput = ({ item, showLabels = true, updateStartValue, updateEndValue, }) => {
3636
- return (jsxRuntime.jsxs("div", { className: 'tw:grid tw:grid-cols-2 tw:gap-2', children: [jsxRuntime.jsx(TextInput, { type: 'date', placeholder: 'start', dataField: 'start', inputStyle: 'tw:text-sm tw:px-2', labelTitle: showLabels ? 'start' : '', defaultValue: item && item.start ? item.start.substring(0, 10) : '', autocomplete: 'one-time-code', updateFormValue: updateStartValue }), jsxRuntime.jsx(TextInput, { type: 'date', placeholder: 'end', dataField: 'end', inputStyle: 'tw:text-sm tw:px-2', labelTitle: showLabels ? 'end' : '', defaultValue: item && item.end ? item.end.substring(0, 10) : '', autocomplete: 'one-time-code', updateFormValue: updateEndValue })] }));
3637
- };
3638
-
3639
- /**
3640
- * @category Map
3641
- */
3642
- const PopupTextInput = ({ dataField, placeholder, style, item, }) => {
3643
- return (jsxRuntime.jsx(TextInput, { defaultValue: item?.name ? item.name : '', dataField: dataField, placeholder: placeholder, inputStyle: style, type: 'text', containerStyle: 'tw:mt-4' }));
3644
- };
3645
-
3646
- /**
3647
- * @category Map
3648
- */
3649
- const PopupCheckboxInput = ({ dataField, label, item, }) => {
3650
- return (jsxRuntime.jsxs("label", { htmlFor: item?.id, className: 'tw:label tw:justify-normal tw:pt-1 tw:pb-1', children: [jsxRuntime.jsx("input", { id: item?.id, type: 'checkbox', name: dataField, className: 'tw:checkbox tw:checkbox-xs tw:checkbox-success', checked: item?.public_edit }), jsxRuntime.jsx("span", { className: 'tw:text-sm tw:label-text tw:mx-2 tw:cursor-pointer', children: label })] }));
3651
- };
3652
-
3653
- function CalendarDaysIcon({
3654
- title,
3655
- titleId,
3656
- ...props
3657
- }, svgRef) {
3658
- return /*#__PURE__*/React__namespace.createElement("svg", Object.assign({
3659
- xmlns: "http://www.w3.org/2000/svg",
3660
- viewBox: "0 0 24 24",
3661
- fill: "currentColor",
3662
- "aria-hidden": "true",
3663
- "data-slot": "icon",
3664
- ref: svgRef,
3665
- "aria-labelledby": titleId
3666
- }, props), title ? /*#__PURE__*/React__namespace.createElement("title", {
3667
- id: titleId
3668
- }, title) : null, /*#__PURE__*/React__namespace.createElement("path", {
3669
- d: "M12.75 12.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM7.5 15.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM8.25 17.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM9.75 15.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM10.5 17.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM12 15.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM12.75 17.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM14.25 15.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM15 17.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM16.5 15.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM15 12.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM16.5 13.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Z"
3670
- }), /*#__PURE__*/React__namespace.createElement("path", {
3671
- fillRule: "evenodd",
3672
- d: "M6.75 2.25A.75.75 0 0 1 7.5 3v1.5h9V3A.75.75 0 0 1 18 3v1.5h.75a3 3 0 0 1 3 3v11.25a3 3 0 0 1-3 3H5.25a3 3 0 0 1-3-3V7.5a3 3 0 0 1 3-3H6V3a.75.75 0 0 1 .75-.75Zm13.5 9a1.5 1.5 0 0 0-1.5-1.5H5.25a1.5 1.5 0 0 0-1.5 1.5v7.5a1.5 1.5 0 0 0 1.5 1.5h13.5a1.5 1.5 0 0 0 1.5-1.5v-7.5Z",
3673
- clipRule: "evenodd"
3674
- }));
3675
- }
3676
- const ForwardRef$6 = /*#__PURE__*/ React__namespace.forwardRef(CalendarDaysIcon);
3677
-
3678
- /**
3679
- * @category Map
3680
- */
3681
- const StartEndView = ({ item }) => {
3682
- return (jsxRuntime.jsxs("div", { className: 'tw:flex tw:flex-row tw:mb-4 tw:mt-1', children: [jsxRuntime.jsxs("div", { className: 'tw:basis-2/5 tw:flex tw:flex-row', children: [jsxRuntime.jsx(ForwardRef$6, { className: 'tw:h-4 tw:w-4 tw:mr-2' }), jsxRuntime.jsx("time", { className: 'tw:align-middle', dateTime: item && item.start ? item.start.substring(0, 10) : '', children: item && item.start ? new Date(item.start).toLocaleDateString() : '' })] }), jsxRuntime.jsx("div", { className: 'tw:basis-1/5 tw:place-content-center', children: jsxRuntime.jsx("span", { children: "-" }) }), jsxRuntime.jsxs("div", { className: 'tw:basis-2/5 tw:flex tw:flex-row', children: [jsxRuntime.jsx(ForwardRef$6, { className: 'tw:h-4 tw:w-4 tw:mr-2' }), jsxRuntime.jsx("time", { className: 'tw:align-middle', dateTime: item && item.end ? item.end.substring(0, 10) : '', children: item && item.end ? new Date(item.end).toLocaleDateString() : '' })] })] }));
3683
- };
3684
-
3685
- /**
3686
- * @category Map
3687
- */
3688
- const PopupButton = ({ url, parameterField, text, item, }) => {
3689
- const params = new URLSearchParams(window.location.search);
3690
- const getItemTags = useGetItemTags();
3691
- return (jsxRuntime.jsx(reactRouterDom.Link, { to: `${url}/${parameterField ? item?.id : ''}?${params}`, children: jsxRuntime.jsx("button", { style: {
3692
- backgroundColor: `${item?.color ?? (item && (getItemTags(item) && getItemTags(item)[0] && getItemTags(item)[0].color ? getItemTags(item)[0].color : (item?.layer?.markerDefaultColor ?? '#000')))}`,
3693
- }, className: 'tw:btn tw:text-white tw:btn-sm tw:float-right tw:mt-1', children: text }) }));
3694
- };
3096
+ adminRole && setAdminRole(adminRole);
3097
+ data && setPermissionData(data);
3098
+ api && setPermissionApi(api);
3099
+ // eslint-disable-next-line react-hooks/exhaustive-deps
3100
+ }, [api, data, adminRole, user]);
3101
+ return jsxRuntime.jsx(jsxRuntime.Fragment, {});
3102
+ }
3695
3103
 
3696
3104
  const themes = [
3697
3105
  'default',
@@ -3721,6 +3129,27 @@ const ThemeControl = () => {
3721
3129
  return (jsxRuntime.jsxs("div", { className: 'tw:dropdown tw:mr-2', children: [jsxRuntime.jsxs("div", { tabIndex: 0, role: 'button', className: 'tw:btn tw:m-1', children: ["Theme", jsxRuntime.jsx("svg", { width: '12px', height: '12px', className: 'tw:inline-block tw:h-2 tw:w-2 tw:fill-current tw:opacity-60', xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 2048 2048', children: jsxRuntime.jsx("path", { d: 'M1799 349l242 241-1017 1017L7 590l242-241 775 775 775-775z' }) })] }), jsxRuntime.jsx("ul", { tabIndex: 0, className: 'tw:dropdown-content tw:bg-base-200 tw:rounded-box tw:z-1 tw:w-36 tw:p-2 tw:shadow-2xl', children: themes.map((t) => (jsxRuntime.jsx("li", { children: jsxRuntime.jsx("input", { className: `tw:btn ${theme === t ? 'tw:bg-base-300' : ''} tw:btn-sm tw:btn-block tw:btn-ghost tw:justify-start`, type: 'radio', name: 'theme', value: t, checked: theme === t, onChange: () => setTheme(t), "aria-label": t.toLowerCase() }) }, t))) })] }));
3722
3130
  };
3723
3131
 
3132
+ function EllipsisVerticalIcon({
3133
+ title,
3134
+ titleId,
3135
+ ...props
3136
+ }, svgRef) {
3137
+ return /*#__PURE__*/React__namespace.createElement("svg", Object.assign({
3138
+ xmlns: "http://www.w3.org/2000/svg",
3139
+ viewBox: "0 0 16 16",
3140
+ fill: "currentColor",
3141
+ "aria-hidden": "true",
3142
+ "data-slot": "icon",
3143
+ ref: svgRef,
3144
+ "aria-labelledby": titleId
3145
+ }, props), title ? /*#__PURE__*/React__namespace.createElement("title", {
3146
+ id: titleId
3147
+ }, title) : null, /*#__PURE__*/React__namespace.createElement("path", {
3148
+ d: "M8 2a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM8 6.5a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM9.5 12.5a1.5 1.5 0 1 0-3 0 1.5 1.5 0 0 0 3 0Z"
3149
+ }));
3150
+ }
3151
+ const ForwardRef$9 = /*#__PURE__*/ React__namespace.forwardRef(EllipsisVerticalIcon);
3152
+
3724
3153
  const UserControl = () => {
3725
3154
  const { isAuthenticated, user, logout } = useAuth();
3726
3155
  const appState = useAppState();
@@ -4038,6 +3467,43 @@ function SetNewPasswordPage() {
4038
3467
  onClick: () => onReset(), children: loading ? jsxRuntime.jsx("span", { className: 'tw:loading tw:loading-spinner' }) : 'Set' }) })] }));
4039
3468
  }
4040
3469
 
3470
+ /**
3471
+ * @category Input
3472
+ */
3473
+ function TextAreaInput({ labelTitle, dataField, labelStyle, containerStyle, inputStyle, defaultValue, placeholder, required = true, updateFormValue, }) {
3474
+ const ref = React.useRef(null);
3475
+ const [inputValue, setInputValue] = React.useState(defaultValue);
3476
+ React.useEffect(() => {
3477
+ setInputValue(defaultValue);
3478
+ }, [defaultValue]);
3479
+ const handleChange = (e) => {
3480
+ const newValue = e.target.value;
3481
+ setInputValue(newValue);
3482
+ if (updateFormValue) {
3483
+ updateFormValue(newValue);
3484
+ }
3485
+ };
3486
+ return (jsxRuntime.jsxs("div", { className: `tw:form-control tw:w-full ${containerStyle ?? ''}`, children: [labelTitle ? (jsxRuntime.jsx("label", { className: 'tw:label', children: jsxRuntime.jsx("span", { className: `tw:label-text tw:text-base-content ${labelStyle ?? ''}`, children: labelTitle }) })) : null, jsxRuntime.jsx("textarea", { required: required, ref: ref, value: inputValue, name: dataField, className: `tw:textarea tw:textarea-bordered tw:w-full tw:leading-5 ${inputStyle ?? ''}`, placeholder: placeholder ?? '', onChange: handleChange })] }));
3487
+ }
3488
+
3489
+ /**
3490
+ * @category Input
3491
+ */
3492
+ function TextInput({ labelTitle, labelStyle, type, dataField, containerStyle, inputStyle, defaultValue, placeholder, autocomplete, pattern, required = true, updateFormValue, }) {
3493
+ const [inputValue, setInputValue] = React.useState(defaultValue ?? '');
3494
+ React.useEffect(() => {
3495
+ setInputValue(defaultValue ?? '');
3496
+ }, [defaultValue]);
3497
+ const handleChange = (e) => {
3498
+ const newValue = e.target.value;
3499
+ setInputValue(newValue);
3500
+ if (updateFormValue) {
3501
+ updateFormValue(newValue);
3502
+ }
3503
+ };
3504
+ return (jsxRuntime.jsxs("div", { className: `tw:form-control ${containerStyle ?? ''}`, children: [labelTitle ? (jsxRuntime.jsx("label", { className: 'tw:label', children: jsxRuntime.jsx("span", { className: `tw:label-text tw:text-base-content ${labelStyle ?? ''}`, children: labelTitle }) })) : null, jsxRuntime.jsx("input", { required: required, pattern: pattern, type: type ?? 'text', name: dataField, value: inputValue, placeholder: placeholder ?? '', autoComplete: autocomplete, onChange: handleChange, className: `tw:input tw:input-bordered tw:w-full ${inputStyle ?? ''}` })] }));
3505
+ }
3506
+
4041
3507
  function Subtitle({ styleClass, children }) {
4042
3508
  return jsxRuntime.jsx("div", { className: `tw:text-xl tw:font-semibold ${styleClass}`, children: children });
4043
3509
  }
@@ -4072,6 +3538,77 @@ const SelectUser = () => {
4072
3538
  }) }) }) }), jsxRuntime.jsx("div", { className: 'tw:w-full tw:grid tw:mt-4', children: jsxRuntime.jsx(reactRouterDom.Link, { className: 'tw:place-self-center ', to: '/attestation-form' + '?to=' + selectedUsers.map((u) => u, ','), children: jsxRuntime.jsx("button", { className: 'tw:btn tw:px-8', children: "Next" }) }) })] }));
4073
3539
  };
4074
3540
 
3541
+ /**
3542
+ * @category Map
3543
+ */
3544
+ const PopupTextAreaInput$1 = ({ dataField, placeholder, style, item, }) => {
3545
+ return (jsxRuntime.jsx(TextAreaInput, { defaultValue: item?.text ? item.text : '', dataField: dataField, placeholder: placeholder, inputStyle: style }));
3546
+ };
3547
+
3548
+ /**
3549
+ * @category Map
3550
+ */
3551
+ const PopupStartEndInput$1 = ({ item, showLabels = true, updateStartValue, updateEndValue, }) => {
3552
+ return (jsxRuntime.jsxs("div", { className: 'tw:grid tw:grid-cols-2 tw:gap-2', children: [jsxRuntime.jsx(TextInput, { type: 'date', placeholder: 'start', dataField: 'start', inputStyle: 'tw:text-sm tw:px-2', labelTitle: showLabels ? 'start' : '', defaultValue: item && item.start ? item.start.substring(0, 10) : '', autocomplete: 'one-time-code', updateFormValue: updateStartValue }), jsxRuntime.jsx(TextInput, { type: 'date', placeholder: 'end', dataField: 'end', inputStyle: 'tw:text-sm tw:px-2', labelTitle: showLabels ? 'end' : '', defaultValue: item && item.end ? item.end.substring(0, 10) : '', autocomplete: 'one-time-code', updateFormValue: updateEndValue })] }));
3553
+ };
3554
+
3555
+ /**
3556
+ * @category Map
3557
+ */
3558
+ const PopupTextInput$1 = ({ dataField, placeholder, style, item, }) => {
3559
+ return (jsxRuntime.jsx(TextInput, { defaultValue: item?.name ? item.name : '', dataField: dataField, placeholder: placeholder, inputStyle: style, type: 'text', containerStyle: 'tw:mt-4' }));
3560
+ };
3561
+
3562
+ /**
3563
+ * @category Map
3564
+ */
3565
+ const PopupCheckboxInput$1 = ({ dataField, label, item, }) => {
3566
+ return (jsxRuntime.jsxs("label", { htmlFor: item?.id, className: 'tw:label tw:justify-normal tw:pt-1 tw:pb-1', children: [jsxRuntime.jsx("input", { id: item?.id, type: 'checkbox', name: dataField, className: 'tw:checkbox tw:checkbox-xs tw:checkbox-success', checked: item?.public_edit }), jsxRuntime.jsx("span", { className: 'tw:text-sm tw:label-text tw:mx-2 tw:cursor-pointer', children: label })] }));
3567
+ };
3568
+
3569
+ function CalendarDaysIcon({
3570
+ title,
3571
+ titleId,
3572
+ ...props
3573
+ }, svgRef) {
3574
+ return /*#__PURE__*/React__namespace.createElement("svg", Object.assign({
3575
+ xmlns: "http://www.w3.org/2000/svg",
3576
+ viewBox: "0 0 24 24",
3577
+ fill: "currentColor",
3578
+ "aria-hidden": "true",
3579
+ "data-slot": "icon",
3580
+ ref: svgRef,
3581
+ "aria-labelledby": titleId
3582
+ }, props), title ? /*#__PURE__*/React__namespace.createElement("title", {
3583
+ id: titleId
3584
+ }, title) : null, /*#__PURE__*/React__namespace.createElement("path", {
3585
+ d: "M12.75 12.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM7.5 15.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM8.25 17.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM9.75 15.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM10.5 17.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM12 15.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM12.75 17.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM14.25 15.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM15 17.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM16.5 15.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5ZM15 12.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM16.5 13.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Z"
3586
+ }), /*#__PURE__*/React__namespace.createElement("path", {
3587
+ fillRule: "evenodd",
3588
+ d: "M6.75 2.25A.75.75 0 0 1 7.5 3v1.5h9V3A.75.75 0 0 1 18 3v1.5h.75a3 3 0 0 1 3 3v11.25a3 3 0 0 1-3 3H5.25a3 3 0 0 1-3-3V7.5a3 3 0 0 1 3-3H6V3a.75.75 0 0 1 .75-.75Zm13.5 9a1.5 1.5 0 0 0-1.5-1.5H5.25a1.5 1.5 0 0 0-1.5 1.5v7.5a1.5 1.5 0 0 0 1.5 1.5h13.5a1.5 1.5 0 0 0 1.5-1.5v-7.5Z",
3589
+ clipRule: "evenodd"
3590
+ }));
3591
+ }
3592
+ const ForwardRef$8 = /*#__PURE__*/ React__namespace.forwardRef(CalendarDaysIcon);
3593
+
3594
+ /**
3595
+ * @category Map
3596
+ */
3597
+ const StartEndView$1 = ({ item }) => {
3598
+ return (jsxRuntime.jsxs("div", { className: 'tw:flex tw:flex-row tw:mb-4 tw:mt-1', children: [jsxRuntime.jsxs("div", { className: 'tw:basis-2/5 tw:flex tw:flex-row', children: [jsxRuntime.jsx(ForwardRef$8, { className: 'tw:h-4 tw:w-4 tw:mr-2' }), jsxRuntime.jsx("time", { className: 'tw:align-middle', dateTime: item && item.start ? item.start.substring(0, 10) : '', children: item && item.start ? new Date(item.start).toLocaleDateString() : '' })] }), jsxRuntime.jsx("div", { className: 'tw:basis-1/5 tw:place-content-center', children: jsxRuntime.jsx("span", { children: "-" }) }), jsxRuntime.jsxs("div", { className: 'tw:basis-2/5 tw:flex tw:flex-row', children: [jsxRuntime.jsx(ForwardRef$8, { className: 'tw:h-4 tw:w-4 tw:mr-2' }), jsxRuntime.jsx("time", { className: 'tw:align-middle', dateTime: item && item.end ? item.end.substring(0, 10) : '', children: item && item.end ? new Date(item.end).toLocaleDateString() : '' })] })] }));
3599
+ };
3600
+
3601
+ /**
3602
+ * @category Map
3603
+ */
3604
+ const PopupButton$1 = ({ url, parameterField, text, item, }) => {
3605
+ const params = new URLSearchParams(window.location.search);
3606
+ const getItemTags = useGetItemTags();
3607
+ return (jsxRuntime.jsx(reactRouterDom.Link, { to: `${url}/${parameterField ? item?.id : ''}?${params}`, children: jsxRuntime.jsx("button", { style: {
3608
+ backgroundColor: `${item?.color ?? (item && (getItemTags(item) && getItemTags(item)[0] && getItemTags(item)[0].color ? getItemTags(item)[0].color : (item?.layer?.markerDefaultColor ?? '#000')))}`,
3609
+ }, className: 'tw:btn tw:text-white tw:btn-sm tw:float-right tw:mt-1', children: text }) }));
3610
+ };
3611
+
4075
3612
  function PlusIcon({
4076
3613
  title,
4077
3614
  titleId,
@@ -4095,15 +3632,203 @@ function PlusIcon({
4095
3632
  d: "M12 4.5v15m7.5-7.5h-15"
4096
3633
  }));
4097
3634
  }
4098
- const ForwardRef$5 = /*#__PURE__*/ React__namespace.forwardRef(PlusIcon);
3635
+ const ForwardRef$7 = /*#__PURE__*/ React__namespace.forwardRef(PlusIcon);
4099
3636
 
4100
3637
  function PlusButton({ layer, triggerAction, color, collection = 'items', }) {
4101
3638
  const hasUserPermission = useHasUserPermission();
4102
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: hasUserPermission(collection, 'create', undefined, layer) && (jsxRuntime.jsx("div", { className: 'tw:dropdown tw:dropdown-top tw:dropdown-end tw:dropdown-hover tw:z-3000 tw:absolute tw:right-4 tw:bottom-4', children: jsxRuntime.jsx("button", { tabIndex: 0, className: 'tw:z-500 tw:btn tw:btn-circle tw:shadow', onClick: () => {
4103
- triggerAction();
4104
- }, style: { backgroundColor: color, color: '#fff' }, children: jsxRuntime.jsx(ForwardRef$5, { className: 'tw:w-5 tw:h-5 tw:stroke-[2.5]' }) }) })) }));
3639
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: hasUserPermission(collection, 'create', undefined, layer) && (jsxRuntime.jsx("div", { className: 'tw:dropdown tw:dropdown-top tw:dropdown-end tw:dropdown-hover tw:z-3000 tw:absolute tw:right-4 tw:bottom-4', children: jsxRuntime.jsx("button", { tabIndex: 0, className: 'tw:z-500 tw:btn tw:btn-circle tw:shadow', onClick: () => {
3640
+ triggerAction();
3641
+ }, style: { backgroundColor: color, color: '#fff' }, children: jsxRuntime.jsx(ForwardRef$7, { className: 'tw:w-5 tw:h-5 tw:stroke-[2.5]' }) }) })) }));
3642
+ }
3643
+
3644
+ const goldenRatioConjugate = 0.618033988749895;
3645
+ const randomColor = () => {
3646
+ return hsvToHex((Math.random() + goldenRatioConjugate) % 1, 0.8, 0.7);
3647
+ };
3648
+ function hsvToHex(h, s, v) {
3649
+ let r, g, b;
3650
+ const i = Math.floor(h * 6);
3651
+ const f = h * 6 - i;
3652
+ const p = v * (1 - s);
3653
+ const q = v * (1 - f * s);
3654
+ const t = v * (1 - (1 - f) * s);
3655
+ switch (i % 6) {
3656
+ case 0:
3657
+ r = v;
3658
+ g = t;
3659
+ b = p;
3660
+ break;
3661
+ case 1:
3662
+ r = q;
3663
+ g = v;
3664
+ b = p;
3665
+ break;
3666
+ case 2:
3667
+ r = p;
3668
+ g = v;
3669
+ b = t;
3670
+ break;
3671
+ case 3:
3672
+ r = p;
3673
+ g = q;
3674
+ b = v;
3675
+ break;
3676
+ case 4:
3677
+ r = t;
3678
+ g = p;
3679
+ b = v;
3680
+ break;
3681
+ case 5:
3682
+ r = v;
3683
+ g = p;
3684
+ b = q;
3685
+ break;
3686
+ }
3687
+ return rgbToHex(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255));
3688
+ }
3689
+ const rgbToHex = (r, g, b) => '#' +
3690
+ [r, g, b]
3691
+ .map((x) => {
3692
+ const hex = x.toString(16);
3693
+ return hex.length === 1 ? `0${hex}` : hex;
3694
+ })
3695
+ .join('');
3696
+
3697
+ function PencilIcon({
3698
+ title,
3699
+ titleId,
3700
+ ...props
3701
+ }, svgRef) {
3702
+ return /*#__PURE__*/React__namespace.createElement("svg", Object.assign({
3703
+ xmlns: "http://www.w3.org/2000/svg",
3704
+ viewBox: "0 0 24 24",
3705
+ fill: "currentColor",
3706
+ "aria-hidden": "true",
3707
+ "data-slot": "icon",
3708
+ ref: svgRef,
3709
+ "aria-labelledby": titleId
3710
+ }, props), title ? /*#__PURE__*/React__namespace.createElement("title", {
3711
+ id: titleId
3712
+ }, title) : null, /*#__PURE__*/React__namespace.createElement("path", {
3713
+ d: "M21.731 2.269a2.625 2.625 0 0 0-3.712 0l-1.157 1.157 3.712 3.712 1.157-1.157a2.625 2.625 0 0 0 0-3.712ZM19.513 8.199l-3.712-3.712-12.15 12.15a5.25 5.25 0 0 0-1.32 2.214l-.8 2.685a.75.75 0 0 0 .933.933l2.685-.8a5.25 5.25 0 0 0 2.214-1.32L19.513 8.2Z"
3714
+ }));
3715
+ }
3716
+ const ForwardRef$6 = /*#__PURE__*/ React__namespace.forwardRef(PencilIcon);
3717
+
3718
+ function TrashIcon({
3719
+ title,
3720
+ titleId,
3721
+ ...props
3722
+ }, svgRef) {
3723
+ return /*#__PURE__*/React__namespace.createElement("svg", Object.assign({
3724
+ xmlns: "http://www.w3.org/2000/svg",
3725
+ viewBox: "0 0 24 24",
3726
+ fill: "currentColor",
3727
+ "aria-hidden": "true",
3728
+ "data-slot": "icon",
3729
+ ref: svgRef,
3730
+ "aria-labelledby": titleId
3731
+ }, props), title ? /*#__PURE__*/React__namespace.createElement("title", {
3732
+ id: titleId
3733
+ }, title) : null, /*#__PURE__*/React__namespace.createElement("path", {
3734
+ fillRule: "evenodd",
3735
+ d: "M16.5 4.478v.227a48.816 48.816 0 0 1 3.878.512.75.75 0 1 1-.256 1.478l-.209-.035-1.005 13.07a3 3 0 0 1-2.991 2.77H8.084a3 3 0 0 1-2.991-2.77L4.087 6.66l-.209.035a.75.75 0 0 1-.256-1.478A48.567 48.567 0 0 1 7.5 4.705v-.227c0-1.564 1.213-2.9 2.816-2.951a52.662 52.662 0 0 1 3.369 0c1.603.051 2.815 1.387 2.815 2.951Zm-6.136-1.452a51.196 51.196 0 0 1 3.273 0C14.39 3.05 15 3.684 15 4.478v.113a49.488 49.488 0 0 0-6 0v-.113c0-.794.609-1.428 1.364-1.452Zm-.355 5.945a.75.75 0 1 0-1.5.058l.347 9a.75.75 0 1 0 1.499-.058l-.346-9Zm5.48.058a.75.75 0 1 0-1.498-.058l-.347 9a.75.75 0 0 0 1.5.058l.345-9Z",
3736
+ clipRule: "evenodd"
3737
+ }));
3738
+ }
3739
+ const ForwardRef$5 = /*#__PURE__*/ React__namespace.forwardRef(TrashIcon);
3740
+
3741
+ var TargetDotSVG = 'data:image/svg+xml;base64,PHN2ZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Ryb2tlPSdjdXJyZW50Q29sb3InCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsPSdjdXJyZW50Q29sb3InCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJva2VXaWR0aD0nMCcKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXdCb3g9JzAgMCA1MTIgNTEyJwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPSd3LTUgaC01JwogICAgICAgICAgICAgICAgICAgICAgICAgICAgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJwogICAgICAgICAgICAgICAgICAgICAgICAgID4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9J00yNTYgMGMxNy43IDAgMzIgMTQuMyAzMiAzMlY0Mi40YzkzLjcgMTMuOSAxNjcuNyA4OCAxODEuNiAxODEuNkg0ODBjMTcuNyAwIDMyIDE0LjMgMzIgMzJzLTE0LjMgMzItMzIgMzJINDY5LjZjLTEzLjkgOTMuNy04OCAxNjcuNy0xODEuNiAxODEuNlY0ODBjMCAxNy43LTE0LjMgMzItMzIgMzJzLTMyLTE0LjMtMzItMzJWNDY5LjZDMTMwLjMgNDU1LjcgNTYuMyAzODEuNyA0Mi40IDI4OEgzMmMtMTcuNyAwLTMyLTE0LjMtMzItMzJzMTQuMy0zMiAzMi0zMkg0Mi40QzU2LjMgMTMwLjMgMTMwLjMgNTYuMyAyMjQgNDIuNFYzMmMwLTE3LjcgMTQuMy0zMiAzMi0zMnpNMTA3LjQgMjg4YzEyLjUgNTguMyA1OC40IDEwNC4xIDExNi42IDExNi42VjM4NGMwLTE3LjcgMTQuMy0zMiAzMi0zMnMzMiAxNC4zIDMyIDMydjIwLjZjNTguMy0xMi41IDEwNC4xLTU4LjQgMTE2LjYtMTE2LjZIMzg0Yy0xNy43IDAtMzItMTQuMy0zMi0zMnMxNC4zLTMyIDMyLTMyaDIwLjZDMzkyLjEgMTY1LjcgMzQ2LjMgMTE5LjkgMjg4IDEwNy40VjEyOGMwIDE3LjctMTQuMyAzMi0zMiAzMnMtMzItMTQuMy0zMi0zMlYxMDcuNEMxNjUuNyAxMTkuOSAxMTkuOSAxNjUuNyAxMDcuNCAyMjRIMTI4YzE3LjcgMCAzMiAxNC4zIDMyIDMycy0xNC4zIDMyLTMyIDMySDEwNy40ek0yNTYgMjI0YTMyIDMyIDAgMSAxIDAgNjQgMzIgMzIgMCAxIDEgMC02NHonPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICAgICAgICA8L3N2Zz4=';
3742
+
3743
+ const isClickInsideRectangle = (e, element) => {
3744
+ const r = element.getBoundingClientRect();
3745
+ return e.clientX > r.left && e.clientX < r.right && e.clientY > r.top && e.clientY < r.bottom;
3746
+ };
3747
+ const DialogModal = ({ title, isOpened, onClose, children, showCloseButton = true, closeOnClickOutside = true, className, }) => {
3748
+ const ref = React.useRef(null);
3749
+ React.useEffect(() => {
3750
+ if (isOpened) {
3751
+ ref.current?.showModal();
3752
+ ref.current?.classList.remove('tw:hidden');
3753
+ document.body.classList.add('modal-open'); // prevent bg scroll
3754
+ }
3755
+ else {
3756
+ ref.current?.close();
3757
+ ref.current?.classList.add('tw:hidden');
3758
+ document.body.classList.remove('modal-open');
3759
+ }
3760
+ }, [isOpened]);
3761
+ if (isOpened) {
3762
+ return (jsxRuntime.jsx("dialog", { className: `${className ?? ''} card tw:shadow-xl tw:absolute tw:right-0 tw:top-0 tw:bottom-0 tw:left-0 tw:m-auto tw:transition-opacity tw:duration-300 tw:p-4 tw:max-w-xl tw:bg-base-100`, ref: ref, onCancel: onClose, onClick: (e) => ref.current && !isClickInsideRectangle(e, ref.current) && closeOnClickOutside && onClose(), children: jsxRuntime.jsxs("div", { className: 'card-body tw:p-2', children: [jsxRuntime.jsx("h2", { className: 'tw:text-2xl tw:font-semibold tw:mb-2 tw:text-center', children: title }), children, showCloseButton && (jsxRuntime.jsx("button", { className: 'btn btn-sm btn-circle btn-ghost tw:absolute tw:right-2 tw:top-2', onClick: onClose, children: "\u2715" }))] }) }));
3763
+ }
3764
+ else
3765
+ return jsxRuntime.jsx(jsxRuntime.Fragment, {});
3766
+ };
3767
+
3768
+ function HeaderView({ item, api, editCallback, deleteCallback, setPositionCallback, loading, hideMenu = false, big = false, truncateSubname = true, hideSubname = false, showAddress = false, }) {
3769
+ const [modalOpen, setModalOpen] = React.useState(false);
3770
+ const hasUserPermission = useHasUserPermission();
3771
+ const navigate = reactRouterDom.useNavigate();
3772
+ const appState = useAppState();
3773
+ const [imageLoaded, setImageLoaded] = React.useState(false);
3774
+ const avatar = item.image && appState.assetsApi.url + item.image + '?width=160&heigth=160';
3775
+ const title = item.name;
3776
+ const subtitle = item.subname;
3777
+ const [address] = React.useState('');
3778
+ const params = new URLSearchParams(window.location.search);
3779
+ const openDeleteModal = async (event) => {
3780
+ setModalOpen(true);
3781
+ event.stopPropagation();
3782
+ };
3783
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: 'tw:flex tw:flex-row', children: [jsxRuntime.jsx("div", { className: 'tw:grow tw:max-w-[calc(100%-60px)] }', children: jsxRuntime.jsxs("div", { className: 'flex items-center', children: [avatar && (jsxRuntime.jsx("div", { className: 'tw:avatar', children: jsxRuntime.jsxs("div", { className: `${big ? 'tw:w-20' : 'tw:w-10'} tw:inline tw:items-center tw:justify-center overflow-hidden`, children: [jsxRuntime.jsx("img", { className: 'tw:w-full tw:h-full tw:object-cover tw:rounded-full', src: avatar, alt: item.name + ' logo', onLoad: () => setImageLoaded(true), onError: () => setImageLoaded(false), style: { display: imageLoaded ? 'block' : 'none' } }), !imageLoaded && (jsxRuntime.jsx("div", { className: 'tw:w-full tw:h-full tw:bg-gray-200 tw:rounded-full' }))] }) })), jsxRuntime.jsxs("div", { className: `${avatar ? 'tw:ml-2' : ''} tw:overflow-hidden`, children: [jsxRuntime.jsx("div", { className: `${big ? 'tw:xl:text-3xl tw:text-2xl' : 'tw:text-xl'} tw:font-semibold tw:truncate`, title: title, children: title }), showAddress && address && !hideSubname && (jsxRuntime.jsx("div", { className: `tw:text-xs tw:text-gray-500 ${truncateSubname && 'tw:truncate'}`, children: address })), subtitle && !hideSubname && (jsxRuntime.jsx("div", { className: `tw:text-xs tw:opacity-50 ${truncateSubname && 'tw:truncate'}`, children: subtitle }))] })] }) }), jsxRuntime.jsx("div", { onClick: (e) => e.stopPropagation(), className: `${big ? 'tw:mt-5' : 'tw:mt-1'}`, children: (api?.deleteItem || item.layer?.api?.updateItem) &&
3784
+ (hasUserPermission(api?.collectionName, 'delete', item) ||
3785
+ hasUserPermission(api?.collectionName, 'update', item)) &&
3786
+ !hideMenu && (jsxRuntime.jsxs("div", { className: 'tw:dropdown tw:dropdown-bottom', children: [jsxRuntime.jsx("label", { tabIndex: 0, className: 'tw:bg-base-100 tw:btn tw:m-1 tw:leading-3 tw:border-none tw:min-h-0 tw:h-6', children: jsxRuntime.jsx(ForwardRef$9, { className: 'tw:h-5 tw:w-5' }) }), jsxRuntime.jsxs("ul", { tabIndex: 0, className: 'tw:dropdown-content tw:menu tw:p-2 tw:shadow tw:bg-base-100 tw:rounded-box tw:z-1000', children: [api?.updateItem &&
3787
+ hasUserPermission(api.collectionName, 'update', item) &&
3788
+ editCallback && (jsxRuntime.jsx("li", { children: jsxRuntime.jsx("a", { className: 'tw:text-base-content! tw:cursor-pointer', onClick: (e) => item.layer?.customEditLink
3789
+ ? navigate(`${item.layer.customEditLink}${item.layer.customEditParameter ? `/${item.id}${params && '?' + params}` : ''} `)
3790
+ : editCallback(e), children: jsxRuntime.jsx(ForwardRef$6, { className: 'tw:h-5 tw:w-5' }) }) })), api?.updateItem &&
3791
+ hasUserPermission(api.collectionName, 'update', item) &&
3792
+ setPositionCallback && (jsxRuntime.jsx("li", { children: jsxRuntime.jsx("a", { className: 'tw:text-base-content! tw:cursor-pointer', onClick: setPositionCallback, children: jsxRuntime.jsx(SVG, { src: TargetDotSVG, className: 'tw:w-5 tw:h-5' }) }) })), api?.deleteItem &&
3793
+ hasUserPermission(api.collectionName, 'delete', item) &&
3794
+ deleteCallback && (jsxRuntime.jsx("li", { children: jsxRuntime.jsx("a", { className: 'tw:cursor-pointer tw:text-error!', onClick: openDeleteModal, children: loading ? (jsxRuntime.jsx("span", { className: 'tw:loading tw:loading-spinner tw:loading-sm' })) : (jsxRuntime.jsx(ForwardRef$5, { className: 'tw:h-5 tw:w-5' })) }) }))] })] })) })] }), jsxRuntime.jsx(DialogModal, { isOpened: modalOpen, title: 'Are you sure?', showCloseButton: false, onClose: () => setModalOpen(false), children: jsxRuntime.jsxs("div", { onClick: (e) => e.stopPropagation(), children: [jsxRuntime.jsxs("span", { children: ["Do you want to delete ", jsxRuntime.jsx("b", { children: item.name }), "?"] }), jsxRuntime.jsx("div", { className: 'tw:grid', children: jsxRuntime.jsxs("div", { className: 'tw:flex tw:justify-between', children: [jsxRuntime.jsx("label", { className: 'tw:btn tw:mt-4 tw:btn-error', onClick: (e) => {
3795
+ deleteCallback(e);
3796
+ setModalOpen(false);
3797
+ }, children: "Yes" }), jsxRuntime.jsx("label", { className: 'tw:btn tw:mt-4', onClick: () => setModalOpen(false), children: "No" })] }) })] }) })] }));
4105
3798
  }
4106
3799
 
3800
+ // in miliseconds
3801
+ const units = [
3802
+ { label: 'year', seconds: 31536000 },
3803
+ { label: 'month', seconds: 2592000 },
3804
+ { label: 'week', seconds: 604800 },
3805
+ { label: 'day', seconds: 86400 },
3806
+ { label: 'hour', seconds: 3600 },
3807
+ { label: 'minute', seconds: 60 },
3808
+ { label: 'second', seconds: 1 },
3809
+ ];
3810
+ const timeAgo = (date) => {
3811
+ const time = Math.floor((new Date().valueOf() - new Date(date).valueOf()) / 1000);
3812
+ const { interval, unit } = calculateTimeDifference(time);
3813
+ const suffix = interval === 1 ? '' : 's';
3814
+ return `${interval} ${unit}${suffix} ago`;
3815
+ };
3816
+ const calculateTimeDifference = (time) => {
3817
+ for (const { label, seconds } of units) {
3818
+ const interval = Math.floor(time / seconds);
3819
+ if (interval >= 1) {
3820
+ return {
3821
+ interval,
3822
+ unit: label,
3823
+ };
3824
+ }
3825
+ }
3826
+ return {
3827
+ interval: 0,
3828
+ unit: '',
3829
+ };
3830
+ };
3831
+
4107
3832
  const DateUserInfo = ({ item }) => {
4108
3833
  const [infoExpanded, setInfoExpanded] = React.useState(false);
4109
3834
  return (jsxRuntime.jsxs("div", { className: 'tw:flex tw:-mb-1 tw:flex-row tw:mr-2 tw:-mt-2', onClick: (e) => e.stopPropagation(), children: [infoExpanded ? (jsxRuntime.jsx("p", { className: 'tw:italic tw:min-h-[21px] tw:my-0! tw:text-gray-500', onClick: () => setInfoExpanded(false), children: `${item.date_updated && item.date_updated !== item.date_created ? 'updated' : 'posted'} ${item.user_created?.first_name ? `by ${item.user_created.first_name}` : ''} ${item.date_updated ? timeAgo(item.date_updated) : timeAgo(item.date_created)}` })) : (jsxRuntime.jsx("p", { className: 'tw:my-0! tw:min-h-[21px] tw:font-bold tw:cursor-pointer tw:text-gray-500', onClick: () => setInfoExpanded(true), children: "\u24D8" })), jsxRuntime.jsx("div", { className: 'tw:grow ' })] }));
@@ -4119,7 +3844,7 @@ const ItemCard = ({ i, loading, url, deleteCallback, }) => {
4119
3844
  navigate('/' + i.id + `${params.size > 0 ? `?${params.toString()}` : ''}`);
4120
3845
  else
4121
3846
  navigate(url + i.id + `${params.size > 0 ? `?${params.toString()}` : ''}`);
4122
- }, children: [jsxRuntime.jsx(HeaderView, { loading: loading, item: i, api: i.layer?.api, editCallback: () => navigate('/edit-item/' + i.id), deleteCallback: () => deleteCallback(i) }), jsxRuntime.jsxs("div", { className: 'tw:overflow-y-auto tw:overflow-x-hidden tw:max-h-64 fade', children: [i.layer?.itemType.show_start_end && jsxRuntime.jsx(StartEndView, { item: i }), i.layer?.itemType.show_text && jsxRuntime.jsx(TextView, { truncate: true, text: i.text, itemId: i.id })] }), jsxRuntime.jsx(DateUserInfo, { item: i })] }));
3847
+ }, children: [jsxRuntime.jsx(HeaderView, { loading: loading, item: i, api: i.layer?.api, editCallback: () => navigate('/edit-item/' + i.id), deleteCallback: () => deleteCallback(i) }), jsxRuntime.jsxs("div", { className: 'tw:overflow-y-auto tw:overflow-x-hidden tw:max-h-64 fade', children: [i.layer?.itemType.show_start_end && jsxRuntime.jsx(StartEndView$1, { item: i }), i.layer?.itemType.show_text && jsxRuntime.jsx(TextView$1, { truncate: true, text: i.text, itemId: i.id })] }), jsxRuntime.jsx(DateUserInfo, { item: i })] }));
4123
3848
  };
4124
3849
 
4125
3850
  /**
@@ -4221,7 +3946,7 @@ const OverlayItemsIndexPage = ({ url, layerName, parameterField, plusButton = tr
4221
3946
  : 0;
4222
3947
  return dateB - dateA; // Subtracts milliseconds which are numbers
4223
3948
  })
4224
- .map((i, k) => (jsxRuntime.jsx("div", { className: 'tw:break-inside-avoid tw:mb-6', children: jsxRuntime.jsx(ItemCard, { i: i, loading: loading, url: url, deleteCallback: () => deleteItem(i) }) }, k))), addItemPopupType === 'place' && (jsxRuntime.jsx("form", { ref: tabRef, autoComplete: 'off', onSubmit: (e) => submitNewItem(e), children: jsxRuntime.jsxs("div", { className: 'tw:cursor-pointer tw:break-inside-avoid card tw:border-[1px] tw:border-base-300 card-body tw:shadow-xl tw:bg-base-100 tw:text-base-content tw:p-6 tw:mb-10', children: [jsxRuntime.jsx("label", { className: 'btn btn-sm tw:rounded-2xl btn-circle btn-ghost tw:hover:bg-transparent tw:absolute tw:right-0 tw:top-0 tw:text-gray-600', onClick: () => setAddItemPopupType(''), children: jsxRuntime.jsx("p", { className: 'tw:text-center', children: "\u2715" }) }), jsxRuntime.jsx(TextInput, { type: 'text', placeholder: 'Name', dataField: 'name', defaultValue: '', inputStyle: '' }), layer?.itemType.show_start_end_input && jsxRuntime.jsx(PopupStartEndInput, {}), jsxRuntime.jsx(TextAreaInput, { placeholder: 'Text', dataField: 'text', defaultValue: '', inputStyle: 'tw:h-40 tw:mt-5' }), jsxRuntime.jsx("div", { className: 'tw:flex tw:justify-center', children: jsxRuntime.jsx("button", { className: loading
3949
+ .map((i, k) => (jsxRuntime.jsx("div", { className: 'tw:break-inside-avoid tw:mb-6', children: jsxRuntime.jsx(ItemCard, { i: i, loading: loading, url: url, deleteCallback: () => deleteItem(i) }) }, k))), addItemPopupType === 'place' && (jsxRuntime.jsx("form", { ref: tabRef, autoComplete: 'off', onSubmit: (e) => submitNewItem(e), children: jsxRuntime.jsxs("div", { className: 'tw:cursor-pointer tw:break-inside-avoid card tw:border-[1px] tw:border-base-300 card-body tw:shadow-xl tw:bg-base-100 tw:text-base-content tw:p-6 tw:mb-10', children: [jsxRuntime.jsx("label", { className: 'btn btn-sm tw:rounded-2xl btn-circle btn-ghost tw:hover:bg-transparent tw:absolute tw:right-0 tw:top-0 tw:text-gray-600', onClick: () => setAddItemPopupType(''), children: jsxRuntime.jsx("p", { className: 'tw:text-center', children: "\u2715" }) }), jsxRuntime.jsx(TextInput, { type: 'text', placeholder: 'Name', dataField: 'name', defaultValue: '', inputStyle: '' }), layer?.itemType.show_start_end_input && jsxRuntime.jsx(PopupStartEndInput$1, {}), jsxRuntime.jsx(TextAreaInput, { placeholder: 'Text', dataField: 'text', defaultValue: '', inputStyle: 'tw:h-40 tw:mt-5' }), jsxRuntime.jsx("div", { className: 'tw:flex tw:justify-center', children: jsxRuntime.jsx("button", { className: loading
4225
3950
  ? 'btn btn-disabled tw:mt-5 tw:place-self-center'
4226
3951
  : 'btn tw:mt-5 tw:place-self-center', type: 'submit', children: loading ? jsxRuntime.jsx("span", { className: 'loading loading-spinner' }) : 'Save' }) })] }) }))] }) })] }) }), plusButton && (jsxRuntime.jsx(PlusButton, { layer: layer, triggerAction: () => {
4227
3952
  setAddItemPopupType('place');
@@ -4910,7 +4635,7 @@ const GroupSubHeaderView = ({ item, shareBaseUrl, platforms, }) => (jsxRuntime.j
4910
4635
  : window.location.protocol + '//' + window.location.host + '/item/' + item.id, title: item.name, platforms: platforms }) })] }));
4911
4636
 
4912
4637
  const ProfileStartEndView = ({ item }) => {
4913
- return (jsxRuntime.jsx("div", { className: 'tw:mt-2 tw:px-6 tw:max-w-xs', children: jsxRuntime.jsx(StartEndView, { item: item }) }));
4638
+ return (jsxRuntime.jsx("div", { className: 'tw:mt-2 tw:px-6 tw:max-w-xs', children: jsxRuntime.jsx(StartEndView$1, { item: item }) }));
4914
4639
  };
4915
4640
 
4916
4641
  const get = (value, path, defaultValue) => {
@@ -4934,7 +4659,7 @@ const get = (value, path, defaultValue) => {
4934
4659
  const ProfileTextView = ({ item, dataField = 'text', heading, hideWhenEmpty, }) => {
4935
4660
  const text = get(item, dataField);
4936
4661
  const parsedText = typeof text !== 'string' ? '' : text;
4937
- return (jsxRuntime.jsxs("div", { className: 'tw:my-10 tw:mt-2 tw:px-6', children: [!(text === '' && hideWhenEmpty) && (jsxRuntime.jsx("h2", { className: 'tw:text-lg tw:font-semibold', children: heading })), jsxRuntime.jsx("div", { className: 'tw:mt-2 tw:text-sm', children: jsxRuntime.jsx(TextView, { itemId: item.id, rawText: parsedText }) })] }));
4662
+ return (jsxRuntime.jsxs("div", { className: 'tw:my-10 tw:mt-2 tw:px-6', children: [!(text === '' && hideWhenEmpty) && (jsxRuntime.jsx("h2", { className: 'tw:text-lg tw:font-semibold', children: heading })), jsxRuntime.jsx("div", { className: 'tw:mt-2 tw:text-sm', children: jsxRuntime.jsx(TextView$1, { itemId: item.id, rawText: parsedText }) })] }));
4938
4663
  };
4939
4664
 
4940
4665
  const componentMap$1 = {
@@ -4956,11 +4681,11 @@ const FlexView = ({ item }) => {
4956
4681
  };
4957
4682
 
4958
4683
  const OnepagerView = ({ item }) => {
4959
- return (jsxRuntime.jsxs("div", { className: 'tw:h-full tw:overflow-y-auto fade', children: [jsxRuntime.jsx(GroupSubHeaderView, { item: item, shareBaseUrl: `https://www.wuerdekompass.org/aktivitaeten/gruppensuche/#/gruppe/${item.slug}` }), item.user_created?.first_name && jsxRuntime.jsx(ContactInfoView, { heading: 'Du hast Fragen?', item: item }), jsxRuntime.jsx("div", { className: 'tw:my-10 tw:mt-2 tw:px-6 tw:text-sm ', children: jsxRuntime.jsx(TextView, { itemId: item.id, rawText: item.text ?? 'Keine Beschreibung vorhanden' }) }), item.next_appointment && (jsxRuntime.jsxs("div", { className: 'tw:my-10 tw:px-6', children: [jsxRuntime.jsx("h2", { className: 'tw:text-lg tw:font-semibold', children: "N\u00E4chste Termine" }), jsxRuntime.jsx("div", { className: 'tw:mt-2 tw:text-sm', children: jsxRuntime.jsx(TextView, { itemId: item.id, rawText: item.next_appointment }) })] })), ";"] }));
4684
+ return (jsxRuntime.jsxs("div", { className: 'tw:h-full tw:overflow-y-auto fade', children: [jsxRuntime.jsx(GroupSubHeaderView, { item: item, shareBaseUrl: `https://www.wuerdekompass.org/aktivitaeten/gruppensuche/#/gruppe/${item.slug}` }), item.user_created?.first_name && jsxRuntime.jsx(ContactInfoView, { heading: 'Du hast Fragen?', item: item }), jsxRuntime.jsx("div", { className: 'tw:my-10 tw:mt-2 tw:px-6 tw:text-sm ', children: jsxRuntime.jsx(TextView$1, { itemId: item.id, rawText: item.text ?? 'Keine Beschreibung vorhanden' }) }), item.next_appointment && (jsxRuntime.jsxs("div", { className: 'tw:my-10 tw:px-6', children: [jsxRuntime.jsx("h2", { className: 'tw:text-lg tw:font-semibold', children: "N\u00E4chste Termine" }), jsxRuntime.jsx("div", { className: 'tw:mt-2 tw:text-sm', children: jsxRuntime.jsx(TextView$1, { itemId: item.id, rawText: item.next_appointment }) })] })), ";"] }));
4960
4685
  };
4961
4686
 
4962
4687
  const SimpleView = ({ item }) => {
4963
- return (jsxRuntime.jsx("div", { className: 'tw:mt-8 tw:h-full tw:overflow-y-auto fade tw:px-6', children: jsxRuntime.jsx(TextView, { text: item.text, itemId: item.id }) }));
4688
+ return (jsxRuntime.jsx("div", { className: 'tw:mt-8 tw:h-full tw:overflow-y-auto fade tw:px-6', children: jsxRuntime.jsx(TextView$1, { text: item.text, itemId: item.id }) }));
4964
4689
  };
4965
4690
 
4966
4691
  function LinkIcon({
@@ -5012,7 +4737,7 @@ function ActionButton({ item, triggerAddButton, triggerItemSelected, existingRel
5012
4737
  }, style: {
5013
4738
  backgroundColor,
5014
4739
  color: '#fff',
5015
- }, children: jsxRuntime.jsx(ForwardRef$5, { className: 'tw:w-5 tw:h-5 tw:stroke-[2.5]' }) }))] }), jsxRuntime.jsxs(DialogModal, { title: 'Select', isOpened: modalOpen, onClose: () => setModalOpen(false), className: 'tw:w-xl tw:sm:w-2xl tw:min-h-80 tw:bg-base-200', children: [jsxRuntime.jsx(TextInput, { defaultValue: '', placeholder: '\uD83D\uDD0D Search', containerStyle: 'lg:col-span-2 tw:m-4 ', updateFormValue: (val) => {
4740
+ }, children: jsxRuntime.jsx(ForwardRef$7, { className: 'tw:w-5 tw:h-5 tw:stroke-[2.5]' }) }))] }), jsxRuntime.jsxs(DialogModal, { title: 'Select', isOpened: modalOpen, onClose: () => setModalOpen(false), className: 'tw:w-xl tw:sm:w-2xl tw:min-h-80 tw:bg-base-200', children: [jsxRuntime.jsx(TextInput, { defaultValue: '', placeholder: '\uD83D\uDD0D Search', containerStyle: 'lg:col-span-2 tw:m-4 ', updateFormValue: (val) => {
5016
4741
  setSearch(val);
5017
4742
  } }), jsxRuntime.jsx("div", { className: 'tw:grid tw:grid-cols-1 tw:sm:grid-cols-2', children: filterdItems
5018
4743
  .filter((item) => {
@@ -5092,7 +4817,7 @@ const TabsView = ({ attestations, item, offers, needs, relations, updatePermissi
5092
4817
  setActiveTab(urlTab ? Number(urlTab) : 1);
5093
4818
  // eslint-disable-next-line react-hooks/exhaustive-deps
5094
4819
  }, [location.search]);
5095
- return (jsxRuntime.jsxs("div", { role: 'tablist', className: 'tw:tabs tw:tabs-lift tw:mt-2 tw:mb-2 tw:px-6', children: [jsxRuntime.jsx("input", { type: 'radio', name: 'my_tabs_2', role: 'tab', className: 'tw:tab tw:font-bold tw:ps-2! tw:pe-2! ', "aria-label": `${item.layer?.itemType.icon_as_labels && activeTab !== 1 ? '📝' : '📝\u00A0Info'}`, checked: activeTab === 1 && true, onChange: () => updateActiveTab(1) }), jsxRuntime.jsxs("div", { role: 'tabpanel', className: 'tw:tab-content tw:bg-base-100 tw:rounded-box tw:!h-[calc(100dvh-280px)] tw:overflow-y-auto fade tw:pt-2 tw:pb-4 tw:mb-4 tw:overflow-x-hidden', children: [item.layer?.itemType.show_start_end && (jsxRuntime.jsx("div", { className: 'tw:max-w-xs', children: jsxRuntime.jsx(StartEndView, { item: item }) })), jsxRuntime.jsx(TextView, { text: item.text, itemId: item.id }), jsxRuntime.jsx("div", { className: 'tw:h-4' }), jsxRuntime.jsx(TextView, { text: item.contact, itemId: item.id })] }), item.layer?.itemType.questlog && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("input", { type: 'radio', name: 'my_tabs_2', role: 'tab', className: 'tw:tab tw:font-bold tw:ps-2! tw:pe-2!', "aria-label": `${item.layer.itemType.icon_as_labels && activeTab !== 2 ? '❤️' : '❤️\u00A0Trust'}`, checked: activeTab === 2 && true, onChange: () => updateActiveTab(2) }), jsxRuntime.jsx("div", { role: 'tabpanel', className: 'tw:tab-content tw:bg-base-100 tw:rounded-box tw:!h-[calc(100dvh-280px)] tw:overflow-y-auto fade tw:pt-2 tw:pb-4 tw:mb-4 tw:overflow-x-hidden', children: jsxRuntime.jsx("table", { className: 'sm:tw:table-sm md:tw:table-md tw:w-full', children: jsxRuntime.jsx("tbody", { children: attestations
4820
+ return (jsxRuntime.jsxs("div", { role: 'tablist', className: 'tw:tabs tw:tabs-lift tw:mt-2 tw:mb-2 tw:px-6', children: [jsxRuntime.jsx("input", { type: 'radio', name: 'my_tabs_2', role: 'tab', className: 'tw:tab tw:font-bold tw:ps-2! tw:pe-2! ', "aria-label": `${item.layer?.itemType.icon_as_labels && activeTab !== 1 ? '📝' : '📝\u00A0Info'}`, checked: activeTab === 1 && true, onChange: () => updateActiveTab(1) }), jsxRuntime.jsxs("div", { role: 'tabpanel', className: 'tw:tab-content tw:bg-base-100 tw:rounded-box tw:!h-[calc(100dvh-280px)] tw:overflow-y-auto fade tw:pt-2 tw:pb-4 tw:mb-4 tw:overflow-x-hidden', children: [item.layer?.itemType.show_start_end && (jsxRuntime.jsx("div", { className: 'tw:max-w-xs', children: jsxRuntime.jsx(StartEndView$1, { item: item }) })), jsxRuntime.jsx(TextView$1, { text: item.text, itemId: item.id }), jsxRuntime.jsx("div", { className: 'tw:h-4' }), jsxRuntime.jsx(TextView$1, { text: item.contact, itemId: item.id })] }), item.layer?.itemType.questlog && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("input", { type: 'radio', name: 'my_tabs_2', role: 'tab', className: 'tw:tab tw:font-bold tw:ps-2! tw:pe-2!', "aria-label": `${item.layer.itemType.icon_as_labels && activeTab !== 2 ? '❤️' : '❤️\u00A0Trust'}`, checked: activeTab === 2 && true, onChange: () => updateActiveTab(2) }), jsxRuntime.jsx("div", { role: 'tabpanel', className: 'tw:tab-content tw:bg-base-100 tw:rounded-box tw:!h-[calc(100dvh-280px)] tw:overflow-y-auto fade tw:pt-2 tw:pb-4 tw:mb-4 tw:overflow-x-hidden', children: jsxRuntime.jsx("table", { className: 'sm:tw:table-sm md:tw:table-md tw:w-full', children: jsxRuntime.jsx("tbody", { children: attestations
5096
4821
  .filter((a) => a.to.some((t) => t.directus_users_id === item.user_created?.id))
5097
4822
  .sort((a, b) => new Date(b.date_created).getTime() - new Date(a.date_created).getTime())
5098
4823
  .map((a, i) => (jsxRuntime.jsxs("tr", { children: [jsxRuntime.jsx("td", { children: jsxRuntime.jsx("div", { className: `tw:cursor-pointer tw:text-3xl tw:mask ${a.shape === 'squircle' ? 'tw:mask-squircle' : a.shape === 'circle' ? 'tw:mask-circle' : 'tw:mask-hexagon-2'} tw:p-2 tw:my-2 tw:mr-2 tw:shadow-xl`,
@@ -5102,7 +4827,7 @@ const TabsView = ({ attestations, item, offers, needs, relations, updatePermissi
5102
4827
  a.user_created.first_name, ' '] }), jsxRuntime.jsx("div", { className: 'tw:text-xs opacity-50 tw:text-zinc-500', children: timeAgo(a.date_created) })] })] }) })) : (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsxs("div", { className: 'font-bold', children: [a.user_created.first_name, " "] }), jsxRuntime.jsx("div", { className: 'tw:text-xs opacity-50 tw:text-zinc-500', children: timeAgo(a.date_created) })] })) })] }, i))) }) }) })] })), item.layer?.itemType.offers_and_needs && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("input", { type: 'radio', name: 'my_tabs_2', role: 'tab', className: `tw:tab tw:font-bold tw:ps-2! tw:pe-2! ${!(item.layer.itemType.icon_as_labels && activeTab !== 3) && 'tw:min-w-[10.4em]'} `, "aria-label": `${item.layer.itemType.icon_as_labels && activeTab !== 3 ? '♻️' : '♻️\u00A0Offers & Needs'}`, checked: activeTab === 3 && true, onChange: () => updateActiveTab(3) }), jsxRuntime.jsx("div", { role: 'tabpanel', className: 'tw:tab-content tw:bg-base-100 tw:rounded-box tw:h-[calc(100dvh-268px)] tw:overflow-y-auto fade tw:pt-4 tw:pb-1', children: jsxRuntime.jsx("div", { className: 'tw:h-full', children: jsxRuntime.jsxs("div", { className: 'tw:grid tw:grid-cols-1', children: [offers.length > 0 ? (jsxRuntime.jsxs("div", { className: 'tw:col-span-1', children: [jsxRuntime.jsx("h3", { className: 'tw:-mb-2', children: "Offers" }), jsxRuntime.jsx("div", { className: 'tw:flex tw:flex-wrap tw:mb-4', children: offers.map((o) => (jsxRuntime.jsx(TagView, { tag: o, onClick: () => {
5103
4828
  addFilterTag(o);
5104
4829
  } }, o.id))) })] })) : (''), needs.length > 0 ? (jsxRuntime.jsxs("div", { className: 'tw:col-span-1', children: [jsxRuntime.jsx("h3", { className: 'tw:-mb-2 tw:col-span-1', children: "Needs" }), jsxRuntime.jsx("div", { className: 'tw:flex tw:flex-wrap tw:mb-4', children: needs.map((n) => (jsxRuntime.jsx(TagView, { tag: n, onClick: () => addFilterTag(n) }, n.id))) })] })) : ('')] }) }) })] })), item.layer?.itemType.relations && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("input", { type: 'radio', name: 'my_tabs_2', role: 'tab', className: 'tw:tab tw:font-bold tw:ps-2! tw:pe-2! ', "aria-label": `${item.layer.itemType.icon_as_labels && activeTab !== 7 ? '🔗' : '🔗\u00A0Links'}`, checked: activeTab === 7 && true, onChange: () => updateActiveTab(7) }), jsxRuntime.jsx("div", { role: 'tabpanel', className: 'tw:tab-content tw:bg-base-100 tw:rounded-box tw:!h-[calc(100dvh-280px)] tw:overflow-y-auto tw:pt-4 tw:pb-1 tw:-mr-4 tw:-mb-4 tw:overflow-x-hidden', children: jsxRuntime.jsx("div", { className: 'tw:h-full', children: jsxRuntime.jsxs("div", { className: 'tw:grid tw:grid-cols-1 tw:sm:grid-cols-2 tw:md:grid-cols-1 tw:lg:grid-cols-1 tw:xl:grid-cols-1 tw:2xl:grid-cols-2 tw:pb-4', children: [relations &&
5105
- relations.map((i) => (jsxRuntime.jsxs("div", { className: 'tw:cursor-pointer tw:card tw:bg-base-200 tw:border-[1px] tw:border-base-300 tw:card-body tw:shadow-xl tw:text-base-content tw:p-6 tw:mr-4 tw:mb-4', onClick: () => navigate('/item/' + i.id), children: [jsxRuntime.jsx(LinkedItemsHeaderView, { unlinkPermission: updatePermission, item: i, unlinkCallback: unlinkItem, loading: loading }), jsxRuntime.jsx("div", { className: 'tw:overflow-y-auto tw:overflow-x-hidden tw:max-h-64 fade', children: jsxRuntime.jsx(TextView, { truncate: true, text: i.text, itemId: item.id }) })] }, i.id))), updatePermission && (jsxRuntime.jsx(ActionButton, { collection: 'items', item: item, existingRelations: relations, triggerItemSelected: linkItem }))] }) }) })] }))] }));
4830
+ relations.map((i) => (jsxRuntime.jsxs("div", { className: 'tw:cursor-pointer tw:card tw:bg-base-200 tw:border-[1px] tw:border-base-300 tw:card-body tw:shadow-xl tw:text-base-content tw:p-6 tw:mr-4 tw:mb-4', onClick: () => navigate('/item/' + i.id), children: [jsxRuntime.jsx(LinkedItemsHeaderView, { unlinkPermission: updatePermission, item: i, unlinkCallback: unlinkItem, loading: loading }), jsxRuntime.jsx("div", { className: 'tw:overflow-y-auto tw:overflow-x-hidden tw:max-h-64 fade', children: jsxRuntime.jsx(TextView$1, { truncate: true, text: i.text, itemId: item.id }) })] }, i.id))), updatePermission && (jsxRuntime.jsx(ActionButton, { collection: 'items', item: item, existingRelations: relations, triggerItemSelected: linkItem }))] }) }) })] }))] }));
5106
4831
  };
5107
4832
 
5108
4833
  /**
@@ -5490,7 +5215,7 @@ const GroupSubheaderForm = ({ state, setState, groupStates, groupTypes, }) => {
5490
5215
  };
5491
5216
 
5492
5217
  const ProfileStartEndForm = ({ item, setState, }) => {
5493
- return (jsxRuntime.jsx(PopupStartEndInput, { item: item, showLabels: false, updateEndValue: (e) => setState((prevState) => ({
5218
+ return (jsxRuntime.jsx(PopupStartEndInput$1, { item: item, showLabels: false, updateEndValue: (e) => setState((prevState) => ({
5494
5219
  ...prevState,
5495
5220
  end: e,
5496
5221
  })), updateStartValue: (s) => setState((prevState) => ({
@@ -5708,7 +5433,7 @@ const TabsForm = ({ item, state, setState, updatePermission, linkItem, unlinkIte
5708
5433
  setActiveTab(urlTab ? Number(urlTab) : 1);
5709
5434
  // eslint-disable-next-line react-hooks/exhaustive-deps
5710
5435
  }, [location.search]);
5711
- return (jsxRuntime.jsx("div", { className: 'tw:grow', children: jsxRuntime.jsxs("div", { role: 'tablist', className: 'tw:tabs tw:h-full tw:tabs-lift tw:mt-3', children: [jsxRuntime.jsx("input", { type: 'radio', name: 'my_tabs_2', role: 'tab', className: 'tw:tab ', "aria-label": 'Info', checked: activeTab === 1 && true, onChange: () => updateActiveTab(1) }), jsxRuntime.jsx("div", { role: 'tabpanel', className: 'tw:tab-content tw:bg-base-100 tw:border-(--fallback-bc,oklch(var(--bc)/0.2)) tw:rounded-box tw:!h-[calc(100%-48px)] tw:min-h-56 tw:border-none', children: jsxRuntime.jsxs("div", { className: `tw:flex tw:flex-col tw:h-full ${item.layer.itemType.show_start_end_input && 'tw:pt-4'}`, children: [item.layer.itemType.show_start_end_input && (jsxRuntime.jsx(PopupStartEndInput, { item: item, showLabels: false, updateEndValue: (e) => setState((prevState) => ({
5436
+ return (jsxRuntime.jsx("div", { className: 'tw:grow', children: jsxRuntime.jsxs("div", { role: 'tablist', className: 'tw:tabs tw:h-full tw:tabs-lift tw:mt-3', children: [jsxRuntime.jsx("input", { type: 'radio', name: 'my_tabs_2', role: 'tab', className: 'tw:tab ', "aria-label": 'Info', checked: activeTab === 1 && true, onChange: () => updateActiveTab(1) }), jsxRuntime.jsx("div", { role: 'tabpanel', className: 'tw:tab-content tw:bg-base-100 tw:border-(--fallback-bc,oklch(var(--bc)/0.2)) tw:rounded-box tw:!h-[calc(100%-48px)] tw:min-h-56 tw:border-none', children: jsxRuntime.jsxs("div", { className: `tw:flex tw:flex-col tw:h-full ${item.layer.itemType.show_start_end_input && 'tw:pt-4'}`, children: [item.layer.itemType.show_start_end_input && (jsxRuntime.jsx(PopupStartEndInput$1, { item: item, showLabels: false, updateEndValue: (e) => setState((prevState) => ({
5712
5437
  ...prevState,
5713
5438
  end: e,
5714
5439
  })), updateStartValue: (s) => setState((prevState) => ({
@@ -5727,7 +5452,7 @@ const TabsForm = ({ item, state, setState, updatePermission, linkItem, unlinkIte
5727
5452
  ...prevState,
5728
5453
  needs: v,
5729
5454
  })), placeholder: 'enter your needs', containerStyle: 'tw:bg-transparent tw:w-full tw:h-full tw:mt-3 tw:text-xs tw:h-[calc(100%-1rem)] tw:min-h-[5em] tw:pb-2 tw:overflow-auto' }) })] }) })] })), item.layer?.itemType.relations && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("input", { type: 'radio', name: 'my_tabs_2', role: 'tab', className: 'tw:tab ', "aria-label": 'Links', checked: activeTab === 7 && true, onChange: () => updateActiveTab(7) }), jsxRuntime.jsx("div", { role: 'tabpanel', className: 'tw:tab-content tw:rounded-box tw:!h-[calc(100%-48px)] tw:overflow-y-auto tw:pt-4 tw:overflow-x-hidden fade', children: jsxRuntime.jsx("div", { className: 'tw:h-full', children: jsxRuntime.jsxs("div", { className: 'tw:grid tw:grid-cols-1 tw:sm:grid-cols-2 tw:md:grid-cols-1 tw:lg:grid-cols-1 tw:xl:grid-cols-1 tw:2xl:grid-cols-2 tw:mb-4', children: [state.relations &&
5730
- state.relations.map((i) => (jsxRuntime.jsxs("div", { className: 'tw:cursor-pointer tw:card tw:bg-base-200 tw:border-[1px] tw:border-base-300 tw:card-body tw:shadow-xl tw:text-base-content tw:mx-4 tw:p-6 tw:mb-4', onClick: () => navigate('/item/' + i.id), children: [jsxRuntime.jsx(LinkedItemsHeaderView, { unlinkPermission: updatePermission, item: i, unlinkCallback: (id) => unlinkItem(id, item, updateItem), loading: loading }), jsxRuntime.jsx("div", { className: 'tw:overflow-y-auto tw:overflow-x-hidden tw:max-h-64 fade', children: jsxRuntime.jsx(TextView, { truncate: true, itemId: item.id }) })] }, i.id))), updatePermission && (jsxRuntime.jsx(ActionButton, { customStyle: 'tw:bottom-24!', collection: 'items', item: item, existingRelations: state.relations, triggerItemSelected: (id) => linkItem(id, item, updateItem) }))] }) }) })] }))] }) }));
5455
+ state.relations.map((i) => (jsxRuntime.jsxs("div", { className: 'tw:cursor-pointer tw:card tw:bg-base-200 tw:border-[1px] tw:border-base-300 tw:card-body tw:shadow-xl tw:text-base-content tw:mx-4 tw:p-6 tw:mb-4', onClick: () => navigate('/item/' + i.id), children: [jsxRuntime.jsx(LinkedItemsHeaderView, { unlinkPermission: updatePermission, item: i, unlinkCallback: (id) => unlinkItem(id, item, updateItem), loading: loading }), jsxRuntime.jsx("div", { className: 'tw:overflow-y-auto tw:overflow-x-hidden tw:max-h-64 fade', children: jsxRuntime.jsx(TextView$1, { truncate: true, itemId: item.id }) })] }, i.id))), updatePermission && (jsxRuntime.jsx(ActionButton, { customStyle: 'tw:bottom-24!', collection: 'items', item: item, existingRelations: state.relations, triggerItemSelected: (id) => linkItem(id, item, updateItem) }))] }) }) })] }))] }) }));
5731
5456
  };
5732
5457
 
5733
5458
  /**
@@ -5894,14 +5619,315 @@ function Quests() {
5894
5619
  return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: questsOpen ? (jsxRuntime.jsx("div", { className: 'tw:card tw:w-48 tw:bg-base-100 tw:shadow-xl tw:absolute tw:bottom-4 tw:left-4 tw:z-2000', children: jsxRuntime.jsxs("div", { className: 'tw:card-body tw:p-4 tw:pt-0', children: [jsxRuntime.jsx("div", { className: 'tw:card-actions tw:justify-end', children: jsxRuntime.jsx("label", { className: 'tw:btn tw:btn-sm tw:btn-circle tw:btn-ghost tw:absolute tw:right-1 tw:top-1', onClick: () => setQuestsOpen(false), children: "\u2715" }) }), jsxRuntime.jsxs("h2", { className: 'tw:card-title tw:m-auto ', children: ["Level 1", jsxRuntime.jsx(QuestionMarkIcon, {})] }), jsxRuntime.jsxs("ul", { className: 'tw:flex-row', children: [jsxRuntime.jsx("li", { children: jsxRuntime.jsxs("label", { className: 'tw:label tw:justify-normal tw:pt-1 tw:pb-0', children: [jsxRuntime.jsx("input", { type: 'checkbox', readOnly: true, className: 'tw:checkbox tw:checkbox-xs tw:checkbox-success', checked: isAuthenticated || false }), jsxRuntime.jsx("span", { className: 'tw:text-sm tw:label-text tw:mx-2', children: "Sign Up" })] }) }), jsxRuntime.jsx("li", { children: jsxRuntime.jsxs("label", { className: 'tw:label tw:justify-normal tw:pt-1 tw:pb-0', children: [jsxRuntime.jsx("input", { type: 'checkbox', readOnly: true, className: 'tw:checkbox tw:checkbox-xs tw:checkbox-success', checked: !!profile?.text }), jsxRuntime.jsx("span", { className: 'tw:text-sm tw:label-text tw:mx-2', children: "Fill Profile" })] }) }), jsxRuntime.jsx("li", { children: jsxRuntime.jsxs("label", { className: 'tw:label tw:justify-normal tw:pt-1 tw:pb-0', children: [jsxRuntime.jsx("input", { type: 'checkbox', readOnly: true, className: 'tw:checkbox tw:checkbox-xs tw:checkbox-success', checked: !!profile?.image }), jsxRuntime.jsx("span", { className: 'tw:text-sm tw:label-text tw:mx-2', children: "Upload Avatar" })] }) })] }), ' '] }) })) : ('') }));
5895
5620
  }
5896
5621
 
5622
+ const ItemContext = React.createContext(undefined);
5623
+
5624
+ function templateify(Component) {
5625
+ const TemplateComponent = (props) => {
5626
+ const item = React.useContext(ItemContext);
5627
+ return jsxRuntime.jsx(Component, { ...props, item: item });
5628
+ };
5629
+ return TemplateComponent;
5630
+ }
5631
+
5632
+ function ItemFormPopup(props) {
5633
+ const layerContext = React.useContext(LayerContext);
5634
+ const { menuText, name: activeLayerName } = layerContext;
5635
+ const { popupForm, setPopupForm } = usePopupForm();
5636
+ const [spinner, setSpinner] = React.useState(false);
5637
+ const formRef = React.useRef(null);
5638
+ const map = reactLeaflet.useMap();
5639
+ const addItem = useAddItem();
5640
+ const updateItem = useUpdateItem();
5641
+ const items = useItems();
5642
+ const tags = useTags();
5643
+ const addTag = useAddTag();
5644
+ const resetFilterTags = useResetFilterTags();
5645
+ const { user } = useAuth();
5646
+ const handleSubmit = async (evt) => {
5647
+ if (!popupForm) {
5648
+ throw new Error('Popup form is not defined');
5649
+ }
5650
+ const formItem = {};
5651
+ Array.from(evt.target).forEach((input) => {
5652
+ if (input.name) {
5653
+ formItem[input.name] = input.value;
5654
+ }
5655
+ });
5656
+ formItem.position = {
5657
+ type: 'Point',
5658
+ coordinates: [popupForm.position.lng, popupForm.position.lat],
5659
+ };
5660
+ evt.preventDefault();
5661
+ const name = formItem.name ? formItem.name : user?.first_name;
5662
+ if (!name) {
5663
+ reactToastify.toast.error('Name is must be defined');
5664
+ return;
5665
+ }
5666
+ setSpinner(true);
5667
+ formItem.text &&
5668
+ formItem.text
5669
+ .toLocaleLowerCase()
5670
+ .match(hashTagRegex)
5671
+ ?.map((tag) => {
5672
+ if (!tags.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) {
5673
+ addTag({ id: crypto.randomUUID(), name: tag.slice(1), color: randomColor() });
5674
+ }
5675
+ return null;
5676
+ });
5677
+ if (popupForm.item) {
5678
+ let success = false;
5679
+ try {
5680
+ await popupForm.layer.api?.updateItem({ ...formItem, id: popupForm.item.id });
5681
+ success = true;
5682
+ // eslint-disable-next-line no-catch-all/no-catch-all
5683
+ }
5684
+ catch (error) {
5685
+ reactToastify.toast.error(error.toString());
5686
+ }
5687
+ if (success) {
5688
+ updateItem({ ...popupForm.item, ...formItem });
5689
+ reactToastify.toast.success('Item updated');
5690
+ }
5691
+ setSpinner(false);
5692
+ map.closePopup();
5693
+ }
5694
+ else {
5695
+ const item = items.find((i) => i.user_created?.id === user?.id && i.layer?.id === popupForm.layer.id);
5696
+ const uuid = crypto.randomUUID();
5697
+ let success = false;
5698
+ try {
5699
+ popupForm.layer.userProfileLayer &&
5700
+ item &&
5701
+ (await popupForm.layer.api?.updateItem({ ...formItem, id: item.id }));
5702
+ (!popupForm.layer.userProfileLayer || !item) &&
5703
+ (await popupForm.layer.api?.createItem({
5704
+ ...formItem,
5705
+ name,
5706
+ id: uuid,
5707
+ }));
5708
+ success = true;
5709
+ // eslint-disable-next-line no-catch-all/no-catch-all
5710
+ }
5711
+ catch (error) {
5712
+ reactToastify.toast.error(error.toString());
5713
+ }
5714
+ if (success) {
5715
+ if (popupForm.layer.userProfileLayer && item)
5716
+ updateItem({ ...item, ...formItem });
5717
+ if (!popupForm.layer.userProfileLayer || !item) {
5718
+ addItem({
5719
+ ...formItem,
5720
+ name: (formItem.name ? formItem.name : user?.first_name) ?? '',
5721
+ user_created: user ?? undefined,
5722
+ id: uuid,
5723
+ layer: popupForm.layer,
5724
+ public_edit: !user,
5725
+ });
5726
+ }
5727
+ reactToastify.toast.success('New item created');
5728
+ resetFilterTags();
5729
+ }
5730
+ setSpinner(false);
5731
+ map.closePopup();
5732
+ }
5733
+ setPopupForm(null);
5734
+ };
5735
+ const resetPopup = () => {
5736
+ if (formRef.current) {
5737
+ formRef.current.reset();
5738
+ }
5739
+ };
5740
+ React.useEffect(() => {
5741
+ resetPopup();
5742
+ }, [popupForm?.position]);
5743
+ return (popupForm &&
5744
+ popupForm.layer.name === activeLayerName && (jsxRuntime.jsx(reactLeaflet.Popup, { minWidth: 275, maxWidth: 275, autoPanPadding: [20, 80], eventHandlers: {
5745
+ remove: () => {
5746
+ setTimeout(function () {
5747
+ resetPopup();
5748
+ }, 100);
5749
+ },
5750
+ }, position: popupForm.position, children: jsxRuntime.jsxs("form", { ref: formRef, onReset: resetPopup, autoComplete: 'off', onSubmit: (e) => handleSubmit(e), children: [popupForm.item ? (jsxRuntime.jsx("div", { className: 'tw:h-3' })) : (jsxRuntime.jsx("div", { className: 'tw:flex tw:justify-center', children: jsxRuntime.jsx("b", { className: 'tw:text-xl tw:text-center tw:font-bold', children: menuText }) })), props.children ? (jsxRuntime.jsx(ItemContext.Provider, { value: popupForm.item, children: props.children })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(TextInput, { type: 'text', placeholder: 'Name', dataField: 'name', defaultValue: popupForm.item ? popupForm.item.name : '', inputStyle: '' }), jsxRuntime.jsx(TextAreaInput, { placeholder: 'Text', dataField: 'text', defaultValue: popupForm.item?.text ?? '', inputStyle: 'tw:h-40 tw:mt-5' }, popupForm.position.toString())] })), jsxRuntime.jsx("div", { className: 'tw:flex tw:justify-center', children: jsxRuntime.jsx("button", { className: spinner
5751
+ ? 'tw:btn tw:btn-disabled tw:mt-5 tw:place-self-center'
5752
+ : 'tw:btn tw:mt-5 tw:place-self-center', type: 'submit', children: spinner ? jsxRuntime.jsx("span", { className: 'tw:loading tw:loading-spinner' }) : 'Save' }) })] }) })));
5753
+ }
5754
+
5755
+ /**
5756
+ * @category Item
5757
+ */
5758
+ const PopupForm = ({ children }) => {
5759
+ return jsxRuntime.jsx(ItemFormPopup, { children: children });
5760
+ };
5761
+
5762
+ // eslint-disable-next-line react/display-name
5763
+ const ItemViewPopup = React.forwardRef((props, ref) => {
5764
+ const map = reactLeaflet.useMap();
5765
+ const [loading, setLoading] = React.useState(false);
5766
+ const removeItem = useRemoveItem();
5767
+ const updadateItem = useUpdateItem();
5768
+ const navigate = reactRouterDom.useNavigate();
5769
+ const setSelectPosition = useSetSelectPosition();
5770
+ const { setPopupForm } = usePopupForm();
5771
+ const [infoExpanded, setInfoExpanded] = React.useState(false);
5772
+ const handleEdit = (event) => {
5773
+ event.stopPropagation();
5774
+ map.closePopup();
5775
+ if (!props.item.layer) {
5776
+ throw new Error('Layer is not defined');
5777
+ }
5778
+ setPopupForm({
5779
+ position: new leaflet.LatLng(props.item.position?.coordinates[1], props.item.position?.coordinates[0]),
5780
+ layer: props.item.layer,
5781
+ item: props.item,
5782
+ });
5783
+ };
5784
+ const handleDelete = async (event) => {
5785
+ event.stopPropagation();
5786
+ setLoading(true);
5787
+ let success = false;
5788
+ try {
5789
+ !props.item.layer?.userProfileLayer &&
5790
+ (await props.item.layer?.api?.deleteItem(props.item.id));
5791
+ props.item.layer?.userProfileLayer &&
5792
+ (await props.item.layer.api?.updateItem({ id: props.item.id, position: null }));
5793
+ success = true;
5794
+ // eslint-disable-next-line no-catch-all/no-catch-all
5795
+ }
5796
+ catch (error) {
5797
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
5798
+ reactToastify.toast.error(error.toString());
5799
+ }
5800
+ if (success) {
5801
+ !props.item.layer?.userProfileLayer && removeItem(props.item);
5802
+ props.item.layer?.userProfileLayer && updadateItem({ ...props.item, position: undefined });
5803
+ reactToastify.toast.success('Item deleted');
5804
+ }
5805
+ setLoading(false);
5806
+ map.closePopup();
5807
+ const params = new URLSearchParams(window.location.search);
5808
+ window.history.pushState({}, '', '/' + `${params ? `?${params}` : ''}`);
5809
+ navigate('/');
5810
+ };
5811
+ return (jsxRuntime.jsx(reactLeaflet.Popup, { ref: ref, maxHeight: 377, minWidth: 275, maxWidth: 275, autoPanPadding: [20, 80], children: jsxRuntime.jsxs("div", { className: 'tw:bg-base-100 tw:text-base-content', children: [jsxRuntime.jsx(HeaderView, { api: props.item.layer?.api, item: props.item, editCallback: handleEdit, deleteCallback: handleDelete, setPositionCallback: () => {
5812
+ map.closePopup();
5813
+ setSelectPosition(props.item);
5814
+ navigate('/');
5815
+ }, loading: loading }), jsxRuntime.jsx("div", { className: 'tw:overflow-y-auto tw:overflow-x-hidden tw:max-h-64 fade', children: props.children ?? jsxRuntime.jsx(TextView$1, { text: props.item.text, itemId: props.item.id }) }), jsxRuntime.jsxs("div", { className: 'tw:flex tw:-mb-1 tw:flex-row tw:mr-2 tw:mt-1', children: [infoExpanded ? (jsxRuntime.jsx("p", { className: 'tw:italic tw:min-h-[21px] tw:my-0! tw:opacity-50', children: `${props.item.date_updated && props.item.date_updated !== props.item.date_created ? 'updated' : 'posted'} ${props.item && props.item.user_created && props.item.user_created.first_name ? `by ${props.item.user_created.first_name}` : ''} ${props.item.date_updated ? timeAgo(props.item.date_updated) : timeAgo(props.item.date_created)}` })) : (jsxRuntime.jsx("p", { className: 'tw:my-0! tw:min-h-[21px] tw:font-bold tw:cursor-pointer tw:text-gray-500', onClick: () => setInfoExpanded(true), children: "\u24D8" })), jsxRuntime.jsx("div", { className: 'tw:grow' })] })] }) }));
5816
+ });
5817
+
5818
+ /**
5819
+ * @category Item
5820
+ */
5821
+ const PopupView = ({ children }) => {
5822
+ const layerContext = React.useContext(LayerContext);
5823
+ const { name, markerDefaultColor, markerDefaultColor2, markerShape, markerIcon } = layerContext;
5824
+ const filterTags = useFilterTags();
5825
+ const appState = useAppState();
5826
+ const items = useItems();
5827
+ const getItemTags = useGetItemTags();
5828
+ const addMarker = useAddMarker();
5829
+ const addPopup = useAddPopup();
5830
+ const leafletRefs = useLeafletRefs();
5831
+ const allTagsLoaded = useAllTagsLoaded();
5832
+ const allItemsLoaded = useAllItemsLoaded();
5833
+ const setMarkerClicked = useSetMarkerClicked();
5834
+ const selectPosition = useSelectPosition();
5835
+ const tags = useTags();
5836
+ const [newTagsToAdd, setNewTagsToAdd] = React.useState([]);
5837
+ const [tagsReady, setTagsReady] = React.useState(false);
5838
+ const isLayerVisible = useIsLayerVisible();
5839
+ const isGroupTypeVisible = useIsGroupTypeVisible();
5840
+ const visibleGroupTypes = useVisibleGroupType();
5841
+ const visibleItems = React.useMemo(() => items
5842
+ .filter((item) => item.layer?.name === name)
5843
+ .filter((item) => filterTags.length === 0
5844
+ ? item
5845
+ : filterTags.some((tag) => getItemTags(item).some((filterTag) => filterTag.name.toLocaleLowerCase() === tag.name.toLocaleLowerCase())))
5846
+ .filter((item) => item.layer && isLayerVisible(item.layer))
5847
+ .filter((item) => (item.group_type && isGroupTypeVisible(item.group_type)) ||
5848
+ visibleGroupTypes.length === 0), [
5849
+ filterTags,
5850
+ getItemTags,
5851
+ isGroupTypeVisible,
5852
+ isLayerVisible,
5853
+ items,
5854
+ name,
5855
+ visibleGroupTypes.length,
5856
+ ]);
5857
+ return visibleItems.map((item) => {
5858
+ if (!(item.position?.coordinates[0] && item.position.coordinates[1]))
5859
+ return null;
5860
+ if (item.tags) {
5861
+ item.text += '\n\n';
5862
+ item.tags.map((tag) => {
5863
+ if (!item.text?.includes(`#${encodeTag(tag)}`)) {
5864
+ item.text += `#${encodeTag(tag)}`;
5865
+ }
5866
+ return item.text;
5867
+ });
5868
+ }
5869
+ if (allTagsLoaded && allItemsLoaded) {
5870
+ item.text?.match(hashTagRegex)?.map((tag) => {
5871
+ if (!tags.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase()) &&
5872
+ !newTagsToAdd.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) {
5873
+ const newTag = {
5874
+ id: crypto.randomUUID(),
5875
+ name: tag.slice(1),
5876
+ color: randomColor(),
5877
+ };
5878
+ setNewTagsToAdd((current) => [...current, newTag]);
5879
+ }
5880
+ return null;
5881
+ });
5882
+ !tagsReady && setTagsReady(true);
5883
+ }
5884
+ const itemTags = getItemTags(item);
5885
+ const latitude = item.position.coordinates[1];
5886
+ const longitude = item.position.coordinates[0];
5887
+ let color1 = markerDefaultColor;
5888
+ let color2 = markerDefaultColor2;
5889
+ if (item.color) {
5890
+ color1 = item.color;
5891
+ }
5892
+ else if (itemTags[0]) {
5893
+ color1 = itemTags[0].color;
5894
+ }
5895
+ if (itemTags[0] && item.color) {
5896
+ color2 = itemTags[0].color;
5897
+ }
5898
+ else if (itemTags[1]) {
5899
+ color2 = itemTags[1].color;
5900
+ }
5901
+ return (jsxRuntime.jsx(ItemContext.Provider, { value: item, children: jsxRuntime.jsxs(reactLeaflet.Marker, { ref: (r) => {
5902
+ if (!(item.id in leafletRefs && leafletRefs[item.id].marker === r)) {
5903
+ r && addMarker(item, r);
5904
+ }
5905
+ }, eventHandlers: {
5906
+ click: () => {
5907
+ selectPosition && setMarkerClicked(item);
5908
+ },
5909
+ }, icon: MarkerIconFactory(markerShape, color1, color2, item.markerIcon ?? markerIcon, appState.assetsApi.url), position: [latitude, longitude], children: [jsxRuntime.jsx(ItemViewPopup, { ref: (r) => {
5910
+ if (!(item.id in leafletRefs && leafletRefs[item.id].popup === r)) {
5911
+ r && addPopup(item, r);
5912
+ }
5913
+ }, item: item, children: children }), jsxRuntime.jsx(reactLeaflet.Tooltip, { offset: [0, -38], direction: 'top', children: item.name })] }) }, item.id));
5914
+ });
5915
+ };
5916
+
5917
+ const TextView = templateify(TextView$1);
5918
+ const StartEndView = templateify(StartEndView$1);
5919
+ const PopupTextInput = templateify(PopupTextInput$1);
5920
+ const PopupButton = templateify(PopupButton$1);
5921
+ const PopupCheckboxInput = templateify(PopupCheckboxInput$1);
5922
+ const PopupTextAreaInput = templateify(PopupTextAreaInput$1);
5923
+ const PopupStartEndInput = templateify(PopupStartEndInput$1);
5924
+
5897
5925
  exports.SVG = SVG;
5898
5926
  exports.AppShell = AppShell;
5899
5927
  exports.AttestationForm = AttestationForm;
5900
5928
  exports.AuthProvider = AuthProvider;
5901
5929
  exports.CardPage = CardPage;
5902
5930
  exports.Content = Content;
5903
- exports.ItemForm = ItemForm;
5904
- exports.ItemView = ItemView;
5905
5931
  exports.Layer = Layer;
5906
5932
  exports.LoginPage = LoginPage;
5907
5933
  exports.MapOverlayPage = MapOverlayPage;
@@ -5911,9 +5937,11 @@ exports.OverlayItemsIndexPage = OverlayItemsIndexPage;
5911
5937
  exports.Permissions = Permissions;
5912
5938
  exports.PopupButton = PopupButton;
5913
5939
  exports.PopupCheckboxInput = PopupCheckboxInput;
5940
+ exports.PopupForm = PopupForm;
5914
5941
  exports.PopupStartEndInput = PopupStartEndInput;
5915
5942
  exports.PopupTextAreaInput = PopupTextAreaInput;
5916
5943
  exports.PopupTextInput = PopupTextInput;
5944
+ exports.PopupView = PopupView;
5917
5945
  exports.ProfileForm = ProfileForm;
5918
5946
  exports.ProfileView = ProfileView;
5919
5947
  exports.Quests = Quests;