Spaces:
Running
Running
Commit
·
18dfe1b
1
Parent(s):
d4a2aaa
small style changes
Browse files- io-app-front/src/components/AdvancedAnalysisModal/AdvancedAnalysisModal.jsx +3 -3
- io-app-front/src/components/AdvancedAnalysisModal/AdvancedAnalysisModal.module.css +15 -0
- io-app-front/src/components/AnalysisPanel/AnalysisPanel.jsx +2 -0
- io-app-front/src/components/AnalysisPanel/AnalysisPanel.module.css +15 -0
- io-app-front/src/components/LayerSelector/LayerSelector.jsx +3 -3
- io-app-front/src/components/MapLegend/MapLegend.module.css +3 -2
- io-app-front/src/components/MapView/MapView.jsx +27 -2
- io-app-front/src/components/MapView/MapView.module.css +67 -0
- io-app-front/src/components/SearchBar/SearchBar.module.css +0 -25
- io-app-front/src/hooks/useMap.js +22 -9
- io-app-front/src/index.css +5 -0
io-app-front/src/components/AdvancedAnalysisModal/AdvancedAnalysisModal.jsx
CHANGED
|
@@ -58,13 +58,13 @@ export default function AdvancedAnalysisModal({ opened, onClose, onRunCompare, i
|
|
| 58 |
{!results && (
|
| 59 |
<Center h={500}>
|
| 60 |
<Stack align="center" gap="xl" w="100%" maw={600}>
|
| 61 |
-
<Text size="lg" fw={500} c="dimmed" lts={1}>
|
| 62 |
<Group grow w="100%">
|
| 63 |
<Select label="Model A" data={modelOptions} allowDeselect={false} value={modelA} onChange={setModelA} disabled={isLoading} />
|
| 64 |
<Select label="Model B" data={modelOptions} allowDeselect={false} value={modelB} onChange={setModelB} disabled={isLoading} />
|
| 65 |
</Group>
|
| 66 |
-
<Button fullWidth size="lg" color="blue" onClick={() => onRunCompare(modelA, modelB)} loading={isLoading}>
|
| 67 |
-
|
| 68 |
</Button>
|
| 69 |
</Stack>
|
| 70 |
</Center>
|
|
|
|
| 58 |
{!results && (
|
| 59 |
<Center h={500}>
|
| 60 |
<Stack align="center" gap="xl" w="100%" maw={600}>
|
| 61 |
+
<Text size="lg" fw={500} c="dimmed" lts={1}>Select models to compare</Text>
|
| 62 |
<Group grow w="100%">
|
| 63 |
<Select label="Model A" data={modelOptions} allowDeselect={false} value={modelA} onChange={setModelA} disabled={isLoading} />
|
| 64 |
<Select label="Model B" data={modelOptions} allowDeselect={false} value={modelB} onChange={setModelB} disabled={isLoading} />
|
| 65 |
</Group>
|
| 66 |
+
<Button fullWidth size="lg" color="blue" onClick={() => onRunCompare(modelA, modelB)} loading={isLoading} className={classes.startAnalysisButton}>
|
| 67 |
+
Start Analysis
|
| 68 |
</Button>
|
| 69 |
</Stack>
|
| 70 |
</Center>
|
io-app-front/src/components/AdvancedAnalysisModal/AdvancedAnalysisModal.module.css
CHANGED
|
@@ -289,3 +289,18 @@
|
|
| 289 |
color: rgba(255, 255, 255, 0.9);
|
| 290 |
font-weight: 600;
|
| 291 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 289 |
color: rgba(255, 255, 255, 0.9);
|
| 290 |
font-weight: 600;
|
| 291 |
}
|
| 292 |
+
|
| 293 |
+
.startAnalysisButton {
|
| 294 |
+
transition: transform 0.5s cubic-bezier(0.25, 1, 0.5, 1), background-color 0.4s ease;
|
| 295 |
+
will-change: transform;
|
| 296 |
+
transform: scale(1);
|
| 297 |
+
}
|
| 298 |
+
|
| 299 |
+
.startAnalysisButton:hover {
|
| 300 |
+
transform: scale(1.02);
|
| 301 |
+
}
|
| 302 |
+
|
| 303 |
+
.startAnalysisButton:active {
|
| 304 |
+
transform: scale(0.96);
|
| 305 |
+
transition-duration: 0.1s;
|
| 306 |
+
}
|
io-app-front/src/components/AnalysisPanel/AnalysisPanel.jsx
CHANGED
|
@@ -79,6 +79,7 @@ function AnalysisPanel({
|
|
| 79 |
loading={isSingleLoading}
|
| 80 |
size="md"
|
| 81 |
fullWidth
|
|
|
|
| 82 |
>
|
| 83 |
Run Analysis
|
| 84 |
</Button>
|
|
@@ -90,6 +91,7 @@ function AnalysisPanel({
|
|
| 90 |
disabled={!isLocationReady || isAdvancedLoading}
|
| 91 |
size="md"
|
| 92 |
fullWidth
|
|
|
|
| 93 |
>
|
| 94 |
Advanced Analysis
|
| 95 |
</Button>
|
|
|
|
| 79 |
loading={isSingleLoading}
|
| 80 |
size="md"
|
| 81 |
fullWidth
|
| 82 |
+
className={styles.runAnalysisButton}
|
| 83 |
>
|
| 84 |
Run Analysis
|
| 85 |
</Button>
|
|
|
|
| 91 |
disabled={!isLocationReady || isAdvancedLoading}
|
| 92 |
size="md"
|
| 93 |
fullWidth
|
| 94 |
+
className={styles.advancedAnalysisButton}
|
| 95 |
>
|
| 96 |
Advanced Analysis
|
| 97 |
</Button>
|
io-app-front/src/components/AnalysisPanel/AnalysisPanel.module.css
CHANGED
|
@@ -51,3 +51,18 @@
|
|
| 51 |
backdrop-filter: blur(10px);
|
| 52 |
margin-bottom: 8px;
|
| 53 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
backdrop-filter: blur(10px);
|
| 52 |
margin-bottom: 8px;
|
| 53 |
}
|
| 54 |
+
|
| 55 |
+
.runAnalysisButton, .advancedAnalysisButton {
|
| 56 |
+
transition: transform 0.5s cubic-bezier(0.25, 1, 0.5, 1), background-color 0.4s ease;
|
| 57 |
+
will-change: transform;
|
| 58 |
+
transform: scale(1);
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
.runAnalysisButton:hover, .advancedAnalysisButton:hover {
|
| 62 |
+
transform: scale(1.02);
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
.runAnalysisButton:active, .advancedAnalysisButton:active {
|
| 66 |
+
transform: scale(0.96);
|
| 67 |
+
transition-duration: 0.1s;
|
| 68 |
+
}
|
io-app-front/src/components/LayerSelector/LayerSelector.jsx
CHANGED
|
@@ -6,8 +6,8 @@ const layerOptions = [
|
|
| 6 |
group: 'Main Images',
|
| 7 |
items: [
|
| 8 |
{ label: 'Satellite (RGB)', value: 'rgb' },
|
| 9 |
-
{ label: '
|
| 10 |
-
{ label: '
|
| 11 |
]
|
| 12 |
},
|
| 13 |
{
|
|
@@ -27,7 +27,7 @@ export function LayerSelector({ layersConfig, onLayersChange }) {
|
|
| 27 |
<Divider
|
| 28 |
my="lg"
|
| 29 |
color="gray.8"
|
| 30 |
-
label="Map
|
| 31 |
labelPosition="center"
|
| 32 |
styles={{ label: { color: '#868e96', fontWeight: 600 } }}
|
| 33 |
/>
|
|
|
|
| 6 |
group: 'Main Images',
|
| 7 |
items: [
|
| 8 |
{ label: 'Satellite (RGB)', value: 'rgb' },
|
| 9 |
+
{ label: 'Raw Output', value: 'raw_segmentation' },
|
| 10 |
+
{ label: 'Output (with Spectral Indices)', value: 'image' },
|
| 11 |
]
|
| 12 |
},
|
| 13 |
{
|
|
|
|
| 27 |
<Divider
|
| 28 |
my="lg"
|
| 29 |
color="gray.8"
|
| 30 |
+
label="Map Layers"
|
| 31 |
labelPosition="center"
|
| 32 |
styles={{ label: { color: '#868e96', fontWeight: 600 } }}
|
| 33 |
/>
|
io-app-front/src/components/MapLegend/MapLegend.module.css
CHANGED
|
@@ -22,9 +22,10 @@
|
|
| 22 |
.colorBadge {
|
| 23 |
width: 14px;
|
| 24 |
height: 14px;
|
| 25 |
-
border-radius:
|
| 26 |
-
border: 1px solid rgba(255, 255, 255, 0.
|
| 27 |
flex-shrink: 0;
|
|
|
|
| 28 |
}
|
| 29 |
|
| 30 |
.itemLabel {
|
|
|
|
| 22 |
.colorBadge {
|
| 23 |
width: 14px;
|
| 24 |
height: 14px;
|
| 25 |
+
border-radius: 50%;
|
| 26 |
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
| 27 |
flex-shrink: 0;
|
| 28 |
+
box-shadow: 0 0 8px rgba(0, 0, 0, 0.3);
|
| 29 |
}
|
| 30 |
|
| 31 |
.itemLabel {
|
io-app-front/src/components/MapView/MapView.jsx
CHANGED
|
@@ -4,6 +4,8 @@ import { useMap } from '../../hooks/useMap'
|
|
| 4 |
import { useAnalysisLayers } from '../../hooks/useAnalysisLayers'
|
| 5 |
import MapLegend from '../MapLegend/MapLegend'
|
| 6 |
import LayerOpacitySlider from '../LayerOpacitySlider/LayerOpacitySlider'
|
|
|
|
|
|
|
| 7 |
|
| 8 |
import styles from './MapView.module.css';
|
| 9 |
|
|
@@ -18,7 +20,7 @@ function MapView({
|
|
| 18 |
|
| 19 |
const [localOpacity, setLocalOpacity] = useState(0.5);
|
| 20 |
|
| 21 |
-
const { mapInstance, isMapLoaded } = useMap(
|
| 22 |
mapContainerRef,
|
| 23 |
mapboxAccessToken,
|
| 24 |
selectedLocation,
|
|
@@ -33,6 +35,7 @@ function MapView({
|
|
| 33 |
localOpacity,
|
| 34 |
);
|
| 35 |
|
|
|
|
| 36 |
useEffect(() => {
|
| 37 |
if (!isMapLoaded || !mapInstance) return;
|
| 38 |
|
|
@@ -51,13 +54,35 @@ function MapView({
|
|
| 51 |
{analysisResult && (
|
| 52 |
<>
|
| 53 |
<MapLegend analysisResult={analysisResult} />
|
| 54 |
-
|
| 55 |
<LayerOpacitySlider
|
| 56 |
opacity={localOpacity}
|
| 57 |
onChange={setLocalOpacity}
|
| 58 |
/>
|
| 59 |
</>
|
| 60 |
)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
</div>
|
| 62 |
);
|
| 63 |
}
|
|
|
|
| 4 |
import { useAnalysisLayers } from '../../hooks/useAnalysisLayers'
|
| 5 |
import MapLegend from '../MapLegend/MapLegend'
|
| 6 |
import LayerOpacitySlider from '../LayerOpacitySlider/LayerOpacitySlider'
|
| 7 |
+
import { IconPlus, IconMinus, IconMapPin } from '@tabler/icons-react'
|
| 8 |
+
import { Tooltip } from '@mantine/core'
|
| 9 |
|
| 10 |
import styles from './MapView.module.css';
|
| 11 |
|
|
|
|
| 20 |
|
| 21 |
const [localOpacity, setLocalOpacity] = useState(0.5);
|
| 22 |
|
| 23 |
+
const { mapInstance, isMapLoaded, handleZoomIn, handleZoomOut, handleFlyBackToAnalysis } = useMap(
|
| 24 |
mapContainerRef,
|
| 25 |
mapboxAccessToken,
|
| 26 |
selectedLocation,
|
|
|
|
| 35 |
localOpacity,
|
| 36 |
);
|
| 37 |
|
| 38 |
+
|
| 39 |
useEffect(() => {
|
| 40 |
if (!isMapLoaded || !mapInstance) return;
|
| 41 |
|
|
|
|
| 54 |
{analysisResult && (
|
| 55 |
<>
|
| 56 |
<MapLegend analysisResult={analysisResult} />
|
|
|
|
| 57 |
<LayerOpacitySlider
|
| 58 |
opacity={localOpacity}
|
| 59 |
onChange={setLocalOpacity}
|
| 60 |
/>
|
| 61 |
</>
|
| 62 |
)}
|
| 63 |
+
<div className={styles.mapActionsPanel}>
|
| 64 |
+
<Tooltip label="Zoom In" position="left" withArrow offset={15} openDelay={500} closeDelay={200} classNames={{ tooltip: styles.customTooltip }}>
|
| 65 |
+
<button onClick={handleZoomIn} className={styles.mapActionButton}>
|
| 66 |
+
<IconPlus size={20} stroke={1.5} />
|
| 67 |
+
</button>
|
| 68 |
+
</Tooltip>
|
| 69 |
+
|
| 70 |
+
<div className={styles.actionDivider} />
|
| 71 |
+
|
| 72 |
+
<Tooltip label="Zoom Out" position="left" withArrow offset={15} openDelay={500} closeDelay={200} classNames={{ tooltip: styles.customTooltip }}>
|
| 73 |
+
<button onClick={handleZoomOut} className={styles.mapActionButton}>
|
| 74 |
+
<IconMinus size={20} stroke={1.5} />
|
| 75 |
+
</button>
|
| 76 |
+
</Tooltip>
|
| 77 |
+
|
| 78 |
+
<div className={styles.actionDivider} />
|
| 79 |
+
|
| 80 |
+
<Tooltip label="Fly Back to Analysis" position="left" withArrow offset={15} openDelay={500} closeDelay={200} classNames={{ tooltip: styles.customTooltip }}>
|
| 81 |
+
<button onClick={handleFlyBackToAnalysis} className={styles.mapActionButton}>
|
| 82 |
+
<IconMapPin size={20} stroke={1.5} />
|
| 83 |
+
</button>
|
| 84 |
+
</Tooltip>
|
| 85 |
+
</div>
|
| 86 |
</div>
|
| 87 |
);
|
| 88 |
}
|
io-app-front/src/components/MapView/MapView.module.css
CHANGED
|
@@ -9,3 +9,70 @@
|
|
| 9 |
width: 100%;
|
| 10 |
height: 100%;
|
| 11 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
width: 100%;
|
| 10 |
height: 100%;
|
| 11 |
}
|
| 12 |
+
|
| 13 |
+
.mapActionsPanel {
|
| 14 |
+
position: absolute;
|
| 15 |
+
bottom: 80px;
|
| 16 |
+
right: 20px;
|
| 17 |
+
display: flex;
|
| 18 |
+
flex-direction: column;
|
| 19 |
+
z-index: 100;
|
| 20 |
+
width: 44px;
|
| 21 |
+
|
| 22 |
+
background-color: rgba(10, 10, 12, 0.8);
|
| 23 |
+
backdrop-filter: blur(40px);
|
| 24 |
+
-webkit-backdrop-filter: blur(40px);
|
| 25 |
+
|
| 26 |
+
border: 1px solid rgba(255, 255, 255, 0.08);
|
| 27 |
+
border-radius: 12px;
|
| 28 |
+
box-shadow: 0 12px 48px rgba(0, 0, 0, 0.6);
|
| 29 |
+
|
| 30 |
+
overflow: hidden;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
.mapActionButton {
|
| 34 |
+
width: 44px;
|
| 35 |
+
height: 44px;
|
| 36 |
+
background: transparent;
|
| 37 |
+
border: none;
|
| 38 |
+
color: rgba(255, 255, 255, 0.7);
|
| 39 |
+
cursor: pointer;
|
| 40 |
+
display: flex;
|
| 41 |
+
align-items: center;
|
| 42 |
+
justify-content: center;
|
| 43 |
+
transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
.mapActionButton:hover {
|
| 47 |
+
color: #fff;
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
.actionDivider {
|
| 51 |
+
height: 1px;
|
| 52 |
+
background-color: rgba(255, 255, 255, 0.08);
|
| 53 |
+
width: 28px;
|
| 54 |
+
margin: 0 auto;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
.mapActionButton:active {
|
| 58 |
+
background-color: rgba(255, 255, 255, 0.1);
|
| 59 |
+
transform: scale(0.96);
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
.customTooltip {
|
| 63 |
+
background-color: rgba(10, 10, 12, 0.9) !important;
|
| 64 |
+
backdrop-filter: blur(10px);
|
| 65 |
+
-webkit-backdrop-filter: blur(10px);
|
| 66 |
+
border: 1px solid rgba(255, 255, 255, 0.1) !important;
|
| 67 |
+
color: #fff !important;
|
| 68 |
+
font-size: 12px !important;
|
| 69 |
+
font-weight: 500;
|
| 70 |
+
padding: 6px 12px !important;
|
| 71 |
+
border-radius: 6px !important;
|
| 72 |
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
.customTooltip::before {
|
| 76 |
+
background-color: rgba(10, 10, 12, 0.9) !important;
|
| 77 |
+
border: 1px solid rgba(255, 255, 255, 0.1) !important;
|
| 78 |
+
}
|
io-app-front/src/components/SearchBar/SearchBar.module.css
CHANGED
|
@@ -1,26 +1 @@
|
|
| 1 |
-
.searchInput {
|
| 2 |
-
background-color: #25262b;
|
| 3 |
-
color: #fff;
|
| 4 |
-
border-color: #373a40;
|
| 5 |
-
border-radius: 20px;
|
| 6 |
-
}
|
| 7 |
|
| 8 |
-
.searchInput:focus {
|
| 9 |
-
border-color: #228be6;
|
| 10 |
-
}
|
| 11 |
-
|
| 12 |
-
.searchDropdown {
|
| 13 |
-
background-color: #25262b;
|
| 14 |
-
border-color: #373a40;
|
| 15 |
-
border-radius: 8px;
|
| 16 |
-
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
|
| 17 |
-
}
|
| 18 |
-
|
| 19 |
-
.searchOption {
|
| 20 |
-
color: #c1c2c5;
|
| 21 |
-
transition: background-color 0.2s ease;
|
| 22 |
-
}
|
| 23 |
-
|
| 24 |
-
.searchOption:hover {
|
| 25 |
-
background-color: #2c2e33;
|
| 26 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
io-app-front/src/hooks/useMap.js
CHANGED
|
@@ -36,14 +36,6 @@ export const useMap = (mapContainerRef, mapboxAccessToken, selectedLocation, ana
|
|
| 36 |
'bottom-right'
|
| 37 |
);
|
| 38 |
|
| 39 |
-
mapRef.current.addControl(
|
| 40 |
-
new mapboxgl.NavigationControl({
|
| 41 |
-
showZoom: true,
|
| 42 |
-
showCompass: false
|
| 43 |
-
}),
|
| 44 |
-
'bottom-right'
|
| 45 |
-
);
|
| 46 |
-
|
| 47 |
return () => {
|
| 48 |
mapRef.current?.remove();
|
| 49 |
markerRef.current?.remove();
|
|
@@ -97,5 +89,26 @@ export const useMap = (mapContainerRef, mapboxAccessToken, selectedLocation, ana
|
|
| 97 |
}
|
| 98 |
}, [analysisResult, isMapLoaded]);
|
| 99 |
|
| 100 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 101 |
}
|
|
|
|
| 36 |
'bottom-right'
|
| 37 |
);
|
| 38 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
return () => {
|
| 40 |
mapRef.current?.remove();
|
| 41 |
markerRef.current?.remove();
|
|
|
|
| 89 |
}
|
| 90 |
}, [analysisResult, isMapLoaded]);
|
| 91 |
|
| 92 |
+
const handleZoomIn = () => {
|
| 93 |
+
mapRef.current?.zoomIn({ duration: 300 });
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
const handleZoomOut = () => {
|
| 97 |
+
mapRef.current?.zoomOut({ duration: 300 });
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
const handleFlyBackToAnalysis = () => {
|
| 101 |
+
const target = analysisResult || selectedLocation;
|
| 102 |
+
|
| 103 |
+
if (mapRef.current && target) {
|
| 104 |
+
mapRef.current.flyTo({
|
| 105 |
+
center: [target.lng || target.lon, target.lat],
|
| 106 |
+
zoom: 12,
|
| 107 |
+
essential: true,
|
| 108 |
+
duration: 2500,
|
| 109 |
+
});
|
| 110 |
+
}
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
return { mapInstance, isMapLoaded, handleZoomIn, handleZoomOut, handleFlyBackToAnalysis };
|
| 114 |
}
|
io-app-front/src/index.css
CHANGED
|
@@ -5,3 +5,8 @@
|
|
| 5 |
bottom: 0;
|
| 6 |
left: 0;
|
| 7 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
bottom: 0;
|
| 6 |
left: 0;
|
| 7 |
}
|
| 8 |
+
|
| 9 |
+
.mapboxgl-ctrl-bottom-right {
|
| 10 |
+
right: 20px !important;
|
| 11 |
+
bottom: 20px !important;
|
| 12 |
+
}
|