janpiechota commited on
Commit
18dfe1b
·
1 Parent(s): d4a2aaa

small style changes

Browse files
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}>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}>
67
- START ANALYSIS
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: 'Segmentation', value: 'image' },
10
- { label: 'Raw Segmentation', value: 'raw_segmentation' }
11
  ]
12
  },
13
  {
@@ -27,7 +27,7 @@ export function LayerSelector({ layersConfig, onLayersChange }) {
27
  <Divider
28
  my="lg"
29
  color="gray.8"
30
- label="Map Display"
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: 3px;
26
- border: 1px solid rgba(255, 255, 255, 0.3);
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
- return { mapInstance, isMapLoaded };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ }