SCGR commited on
Commit
dcc22a4
·
1 Parent(s): cc4ade1

image type filter bar

Browse files
docker-compose.yml CHANGED
@@ -9,7 +9,7 @@ services:
9
  POSTGRES_PASSWORD: promptaid
10
  POSTGRES_DB: promptaid
11
  ports:
12
- - "5434:5432" # Changed from 5433 to avoid conflict
13
  volumes:
14
  - pgdata:/var/lib/postgresql/data
15
 
@@ -39,11 +39,7 @@ services:
39
  - minio_data:/data
40
  depends_on:
41
  - postgres
42
- healthcheck:
43
- test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
44
- interval: 30s
45
- timeout: 20s
46
- retries: 3
47
 
48
  app:
49
  build: .
@@ -55,10 +51,8 @@ services:
55
  - DATABASE_URL=postgresql://promptaid:promptaid@postgres:5432/promptaid
56
  - S3_ENDPOINT=http://minio:9000 # Override for container networking
57
  depends_on:
58
- postgres:
59
- condition: service_healthy
60
- minio:
61
- condition: service_healthy
62
  volumes:
63
  - ./py_backend:/app
64
  - /app/__pycache__
 
9
  POSTGRES_PASSWORD: promptaid
10
  POSTGRES_DB: promptaid
11
  ports:
12
+ - "5434:5432"
13
  volumes:
14
  - pgdata:/var/lib/postgresql/data
15
 
 
39
  - minio_data:/data
40
  depends_on:
41
  - postgres
42
+
 
 
 
 
43
 
44
  app:
45
  build: .
 
51
  - DATABASE_URL=postgresql://promptaid:promptaid@postgres:5432/promptaid
52
  - S3_ENDPOINT=http://minio:9000 # Override for container networking
53
  depends_on:
54
+ - postgres
55
+ - minio
 
 
56
  volumes:
57
  - ./py_backend:/app
58
  - /app/__pycache__
frontend/src/pages/ExplorePage/ExplorePage.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import { PageContainer, TextInput, SelectInput, MultiSelectInput, Container, SegmentInput, Spinner } from '@ifrc-go/ui';
2
  import { useState, useEffect, useMemo } from 'react';
3
  import { useNavigate } from 'react-router-dom';
4
  import styles from './ExplorePage.module.css';
@@ -36,6 +36,7 @@ export default function ExplorePage() {
36
  const [catFilter, setCatFilter] = useState('');
37
  const [regionFilter, setRegionFilter] = useState('');
38
  const [countryFilter, setCountryFilter] = useState('');
 
39
  const [sources, setSources] = useState<{s_code: string, label: string}[]>([]);
40
  const [types, setTypes] = useState<{t_code: string, label: string}[]>([]);
41
  const [regions, setRegions] = useState<{r_code: string, label: string}[]>([]);
@@ -145,10 +146,11 @@ export default function ExplorePage() {
145
  c.countries.some(country => country.r_code === regionFilter);
146
  const matchesCountry = !countryFilter ||
147
  c.countries.some(country => country.c_code === countryFilter);
 
148
 
149
- return matchesSearch && matchesSource && matchesCategory && matchesRegion && matchesCountry;
150
  });
151
- }, [captions, search, srcFilter, catFilter, regionFilter, countryFilter]);
152
 
153
 
154
  return (
@@ -246,6 +248,20 @@ export default function ExplorePage() {
246
  disabled={isLoadingFilters}
247
  />
248
  </Container>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
  </div>
250
  </div>
251
 
@@ -255,6 +271,20 @@ export default function ExplorePage() {
255
  <p className="text-sm text-gray-600">
256
  {filtered.length} of {captions.length} examples
257
  </p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
  </div>
259
 
260
  {/* Loading State */}
 
1
+ import { PageContainer, TextInput, SelectInput, MultiSelectInput, Container, SegmentInput, Spinner, Button } from '@ifrc-go/ui';
2
  import { useState, useEffect, useMemo } from 'react';
3
  import { useNavigate } from 'react-router-dom';
4
  import styles from './ExplorePage.module.css';
 
36
  const [catFilter, setCatFilter] = useState('');
37
  const [regionFilter, setRegionFilter] = useState('');
38
  const [countryFilter, setCountryFilter] = useState('');
39
+ const [imageTypeFilter, setImageTypeFilter] = useState('');
40
  const [sources, setSources] = useState<{s_code: string, label: string}[]>([]);
41
  const [types, setTypes] = useState<{t_code: string, label: string}[]>([]);
42
  const [regions, setRegions] = useState<{r_code: string, label: string}[]>([]);
 
146
  c.countries.some(country => country.r_code === regionFilter);
147
  const matchesCountry = !countryFilter ||
148
  c.countries.some(country => country.c_code === countryFilter);
149
+ const matchesImageType = !imageTypeFilter || c.image_type === imageTypeFilter;
150
 
151
+ return matchesSearch && matchesSource && matchesCategory && matchesRegion && matchesCountry && matchesImageType;
152
  });
153
+ }, [captions, search, srcFilter, catFilter, regionFilter, countryFilter, imageTypeFilter]);
154
 
155
 
156
  return (
 
248
  disabled={isLoadingFilters}
249
  />
250
  </Container>
251
+
252
+ <Container withInternalPadding className="bg-white/20 backdrop-blur-sm rounded-md p-2">
253
+ <SelectInput
254
+ name="imageType"
255
+ placeholder={isLoadingFilters ? "Loading..." : "All Image Types"}
256
+ options={imageTypes}
257
+ value={imageTypeFilter || null}
258
+ onChange={(v) => setImageTypeFilter(v as string || '')}
259
+ keySelector={(o) => o.image_type}
260
+ labelSelector={(o) => o.label}
261
+ required={false}
262
+ disabled={isLoadingFilters}
263
+ />
264
+ </Container>
265
  </div>
266
  </div>
267
 
 
271
  <p className="text-sm text-gray-600">
272
  {filtered.length} of {captions.length} examples
273
  </p>
274
+ <Button
275
+ name="clear-filters"
276
+ variant="secondary"
277
+ onClick={() => {
278
+ setSearch('');
279
+ setSrcFilter('');
280
+ setCatFilter('');
281
+ setRegionFilter('');
282
+ setCountryFilter('');
283
+ setImageTypeFilter('');
284
+ }}
285
+ >
286
+ Clear Filters
287
+ </Button>
288
  </div>
289
 
290
  {/* Loading State */}
frontend/src/pages/MapDetailsPage/MapDetailPage.tsx CHANGED
@@ -55,6 +55,7 @@ export default function MapDetailPage() {
55
  const [catFilter, setCatFilter] = useState('');
56
  const [regionFilter, setRegionFilter] = useState('');
57
  const [countryFilter, setCountryFilter] = useState('');
 
58
 
59
  const viewOptions = [
60
  { key: 'explore' as const, label: 'Explore' },
@@ -164,9 +165,10 @@ export default function MapDetailPage() {
164
  map.countries.some(country => country.r_code === regionFilter);
165
  const matchesCountry = !countryFilter ||
166
  map.countries.some(country => country.c_code === countryFilter);
 
167
 
168
- return matchesSearch && matchesSource && matchesCategory && matchesRegion && matchesCountry ? map : null;
169
- }, [map, search, srcFilter, catFilter, regionFilter, countryFilter]);
170
 
171
  const handleContribute = async () => {
172
  if (!map) return;
@@ -346,6 +348,19 @@ export default function MapDetailPage() {
346
  labelSelector={(o) => o.label}
347
  />
348
  </Container>
 
 
 
 
 
 
 
 
 
 
 
 
 
349
  </div>
350
  </div>
351
 
@@ -461,7 +476,14 @@ export default function MapDetailPage() {
461
  onClick={handleContribute}
462
  disabled={isGenerating}
463
  >
464
- {isGenerating ? 'Generating...' : 'Contribute'}
 
 
 
 
 
 
 
465
  </Button>
466
  </Container>
467
 
@@ -506,6 +528,7 @@ export default function MapDetailPage() {
506
  setCatFilter('');
507
  setRegionFilter('');
508
  setCountryFilter('');
 
509
  }}
510
  >
511
  Clear Filters
 
55
  const [catFilter, setCatFilter] = useState('');
56
  const [regionFilter, setRegionFilter] = useState('');
57
  const [countryFilter, setCountryFilter] = useState('');
58
+ const [imageTypeFilter, setImageTypeFilter] = useState('');
59
 
60
  const viewOptions = [
61
  { key: 'explore' as const, label: 'Explore' },
 
165
  map.countries.some(country => country.r_code === regionFilter);
166
  const matchesCountry = !countryFilter ||
167
  map.countries.some(country => country.c_code === countryFilter);
168
+ const matchesImageType = !imageTypeFilter || map.image_type === imageTypeFilter;
169
 
170
+ return matchesSearch && matchesSource && matchesCategory && matchesRegion && matchesCountry && matchesImageType ? map : null;
171
+ }, [map, search, srcFilter, catFilter, regionFilter, countryFilter, imageTypeFilter]);
172
 
173
  const handleContribute = async () => {
174
  if (!map) return;
 
348
  labelSelector={(o) => o.label}
349
  />
350
  </Container>
351
+
352
+ <Container withInternalPadding className="bg-white/20 backdrop-blur-sm rounded-md p-2">
353
+ <SelectInput
354
+ name="imageType"
355
+ placeholder="All Image Types"
356
+ options={imageTypes}
357
+ value={imageTypeFilter || null}
358
+ onChange={(v) => setImageTypeFilter(v as string || '')}
359
+ keySelector={(o) => o.image_type}
360
+ labelSelector={(o) => o.label}
361
+ required={false}
362
+ />
363
+ </Container>
364
  </div>
365
  </div>
366
 
 
476
  onClick={handleContribute}
477
  disabled={isGenerating}
478
  >
479
+ {isGenerating ? (
480
+ <div className="flex items-center gap-2">
481
+ <Spinner className="text-white" />
482
+ <span>Generating...</span>
483
+ </div>
484
+ ) : (
485
+ 'Contribute'
486
+ )}
487
  </Button>
488
  </Container>
489
 
 
528
  setCatFilter('');
529
  setRegionFilter('');
530
  setCountryFilter('');
531
+ setImageTypeFilter('');
532
  }}
533
  >
534
  Clear Filters