fallbacks to defaults if not provided
+ i18nKey='About.team1'
components={{
link1: ,
link2: ,
@@ -277,7 +277,7 @@ class BaseAbout extends React.Component {
}}
/>
fallbacks to defaults if not provided
+ i18nKey='About.team2'
components={{
link1:
}}
diff --git a/frontend/pages/MapPageView.js b/frontend/pages/MapPageView.js
index 96d6279c..f73cc203 100644
--- a/frontend/pages/MapPageView.js
+++ b/frontend/pages/MapPageView.js
@@ -12,7 +12,7 @@ import MapSquareContent from "../components/map-page/MapSquareContent";
import TitleDecoratorContainer from "../components/TitleDecoratorContainer";
import { withTranslation } from "react-i18next";
-function densityOverlay(mapData, selectMapSquare) {
+function densityOverlay(mapData, selectMapSquare, translator) {
const sortedMapData = Object.values(mapData).sort((a, b) => a.num_photos - b.num_photos);
// Gets the max number of photos in a single square out of all squares to form buckets later
@@ -72,29 +72,25 @@ function densityOverlay(mapData, selectMapSquare) {
}
>
- {/* {`${this.props.t('global.mapSquare')} ${square.number} - ${square.photoCount} ${this.props.t('MapPage.photos')}`} */}
+ {`${translator('global.mapSquare')} ${square.number} - ${square.photoCount} ${translator('global.photos')}`}
));
}
-function arrondissementsOverlay(data) {
- return data !== null ? (
- data.map((tract) => {
- return (
-
- );
- })
- ) : (
- <>>
- );
+export function arrondissementsOverlay(data) {
+ return data !== null ? data.map(tract => {
+ return (
+
+ );
+ }) : <>>;
}
export class MapSquareViewer extends React.Component {
@@ -198,7 +194,7 @@ class BaseMapPage extends MapSquareViewer {
async selectMapSquare(mapSquare) {
this.setState({mapSquare: mapSquare, photos: []});
- this.state.mapData.map((ms) => {
+ Object.values(this.state.mapData).map((ms) => {
if (ms.id === mapSquare) {
return this.setState({
mapLat: ms.topLeftCoords.lat,
@@ -236,7 +232,9 @@ class BaseMapPage extends MapSquareViewer {
const arrondissementLabel = this.props.t('global.arrondissement');
const photosAvailableLabel = this.props.t('global.photosAvailable');
mapLayers[arrondissementLabel] = arrondissementsOverlay(this.state.geojsonData);
- mapLayers[photosAvailableLabel] = densityOverlay(this.state.mapData, this.selectMapSquare);
+ mapLayers[photosAvailableLabel] = densityOverlay(
+ this.state.mapData, this.selectMapSquare, this.props.t
+ );
return (
diff --git a/frontend/pages/PhotoView.js b/frontend/pages/PhotoView.js
index 60c6a990..361dfb98 100644
--- a/frontend/pages/PhotoView.js
+++ b/frontend/pages/PhotoView.js
@@ -13,7 +13,7 @@ import TitleDecoratorContainer from "../components/TitleDecoratorContainer";
import { Trans, withTranslation } from "react-i18next";
const TURQUOISE = "#20CCD7";
-const NUM_PHOTOGRAPHERS = 72;
+// const NUM_PHOTOGRAPHERS = 72;
class BasePhotoView extends PhotoViewer {
@@ -266,9 +266,9 @@ class BasePhotoView extends PhotoViewer {
{this.props.photographer_name}
-
#23 out of
+ {/* #23 out of
{NUM_PHOTOGRAPHERS} in collection
+ className={"photo-link"}>{NUM_PHOTOGRAPHERS} in collection */}
>
: <>{this.props.photographer_name} {this.props.photographer_number}>
}
diff --git a/frontend/pages/TagView.js b/frontend/pages/TagView.js
index 19640716..8d796643 100644
--- a/frontend/pages/TagView.js
+++ b/frontend/pages/TagView.js
@@ -3,11 +3,11 @@ import ParisMap, {MAPSQUARE_HEIGHT, MAPSQUARE_WIDTH} from "../components/ParisMa
import * as PropTypes from "prop-types";
import PhotoViewer from "../components/PhotoViewer";
import LoadingPage from "./LoadingPage";
-import { MapSquareViewer } from "./MapPageView";
-import {GeoJSON, Popup, Rectangle} from "react-leaflet";
+import { MapSquareViewer, arrondissementsOverlay } from "./MapPageView";
+import { Popup, Rectangle } from "react-leaflet";
import { Trans, withTranslation } from "react-i18next";
-function densityOverlay(mapSquareData) {
+function densityOverlay(mapSquareData, translator) {
const sortedMapData = Object.values(mapSquareData)
.sort((a, b) => a.num_photos - b.num_photos);
// Gets the max number of photos in a single square out of all squares to form buckets later
@@ -51,8 +51,8 @@ function densityOverlay(mapSquareData) {
key={index}
bounds={mapSquareBounds}>
- Map Square {index}
- {numberOfPhotos} photos to show
+ {translator("global.mapSquare")} {index}
+ {numberOfPhotos} {translator("global.photos")}
);
@@ -61,23 +61,9 @@ function densityOverlay(mapSquareData) {
>);
}
-function arrondissementsOverlay(data) {
- return data !== null ? data.map(tract => {
- return (
-
- );
- }) : <>>;
-}
-
function Mix(bases) {
+ // https://stackoverflow.com/a/61860802
class Bases extends React.Component {
constructor(props) {
super(props);
@@ -151,21 +137,22 @@ class BaseTagView extends Mix([PhotoViewer, MapSquareViewer]) {
render() {
if (this.props.tagPhotos.length === 0) {
- return (<>
- Tag {this.props.tagName} is not in the database.
- >);
+ return
;
}
const tag = this.props.tagName;
const photos = JSON.parse(this.props.tagPhotos);
if (!this.state.mapData || !this.state.filledMapSquares || !this.state.filledMapSquaresData) {
- return (
);
+ return
;
}
const arrondissementLabel = this.props.t("global.arrondissement");
const photosAvailableLabel = this.props.t("global.photosAvailable");
const mapLayers = {};
mapLayers[arrondissementLabel] = arrondissementsOverlay(this.state.geojsonData);
- mapLayers[photosAvailableLabel] = densityOverlay(this.state.filledMapSquaresData);
+ mapLayers[photosAvailableLabel] = densityOverlay(this.state.filledMapSquaresData, this.props.t);
return (<>
From 261b2146c7015be87f74d9ad744d13e9cb4d5745 Mon Sep 17 00:00:00 2001
From: JusticeV452 <55002917+JusticeV452@users.noreply.github.com>
Date: Wed, 26 Jun 2024 13:50:26 -0400
Subject: [PATCH 15/19] Create launch_site.py
---
.../app/management/commands/launch_site.py | 24 +++++++++++++++++++
1 file changed, 24 insertions(+)
create mode 100644 backend/app/management/commands/launch_site.py
diff --git a/backend/app/management/commands/launch_site.py b/backend/app/management/commands/launch_site.py
new file mode 100644
index 00000000..80a9b82c
--- /dev/null
+++ b/backend/app/management/commands/launch_site.py
@@ -0,0 +1,24 @@
+"""
+Django management command launch_site
+"""
+
+import platform
+import subprocess
+
+from django.core.management.base import BaseCommand
+from django.core.management import call_command
+
+
+class Command(BaseCommand):
+ """
+ Custom django-admin command to launch the local website
+ """
+
+ help = "Custom django-admin command to launch the local website"
+
+ def handle(self, *args, **options):
+ on_windows = platform.system() == "Windows"
+ frontend_cmd = [f"npm{'.cmd' if on_windows else ''}", "run", "start"]
+ with subprocess.Popen(frontend_cmd) as frontend:
+ call_command("runserver")
+ frontend.kill()
From e40cd45aa55b4791d87b778a4f726ddd6d0f26df Mon Sep 17 00:00:00 2001
From: JusticeV452 <55002917+JusticeV452@users.noreply.github.com>
Date: Wed, 26 Jun 2024 14:00:48 -0400
Subject: [PATCH 16/19] Updated translation api docstring
---
backend/app/api_views.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/backend/app/api_views.py b/backend/app/api_views.py
index b93ffaf8..d0e48069 100644
--- a/backend/app/api_views.py
+++ b/backend/app/api_views.py
@@ -110,8 +110,7 @@ def photo(request, map_square_number, folder_number, photo_number):
@api_view(['GET'])
def translation(request, language_code):
"""
- API endpoint to get a photo with a map square number of map_square_number
- and photo number of photo_number
+ API endpoint to get text translation dictionary
"""
return Response(TRANSLATIONS)
From 0cf68a2cc00e563df18b6ba3dc32c46eee61cd82 Mon Sep 17 00:00:00 2001
From: JusticeV452 <55002917+JusticeV452@users.noreply.github.com>
Date: Wed, 26 Jun 2024 14:11:29 -0400
Subject: [PATCH 17/19] Made About page headers translatable
---
backend/app/translation_db.py | 2 ++
frontend/pages/About.jsx | 4 ++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/backend/app/translation_db.py b/backend/app/translation_db.py
index 67e8e698..aae32251 100644
--- a/backend/app/translation_db.py
+++ b/backend/app/translation_db.py
@@ -140,8 +140,10 @@ def translate_tag(tag, default=None):
"about": _("About the Project")
},
"About": {
+ "aboutHeader": _("About"),
"context1": _("In May 1970, thousands of amateur photographers spread out across Paris to take pictures. They were participants in a photo contest, “This was Paris in 1970,” organized by the cooperative electronics store the Fnac. Each contestant had been assigned to document a 250m square of the city. By the end of the month, this army of photographers had produced an unprecedented collection of 100,000 photographs: 70,000 black-and-white prints and 30,000 colors slides. This website currently hosts 5,000 color slides from the 13th and 19th arrondissements, areas of the city which were undergoing significant change in 1960s and 1970s."),
"context2": _(" The project This was Paris in 1970 provides tools to explore the rich archive: a
map to see the photos square by square; an
object detector to search for photos of many objects from people to cats, cars to strollers; a similar photo viewer to identify photos by composition rather than subject; and
articles providing context and analysis."),
+ "teamHeader": _("The Team"),
"team1": _("This is Paris in 1970 was created in MIT’s Digital Humanities Lab as a collaboration between DH Fellow
Prof. Catherine Clark,
four dozen undergraduate research associates, and
the instructional staff of the DH Lab. Justice Vidal built out the first version of the site, and Nina Li spearheaded the design work."),
"team2": _("The
Bibliothèque historique de la Ville de Paris holds the contest photographs. Its photo department made this project possible."),
},
diff --git a/frontend/pages/About.jsx b/frontend/pages/About.jsx
index f4e39c03..fae40032 100644
--- a/frontend/pages/About.jsx
+++ b/frontend/pages/About.jsx
@@ -253,7 +253,7 @@ class BaseAbout extends React.Component {
-
+
{this.props.t('About.context1')}
-
+
Date: Wed, 26 Jun 2024 14:34:33 -0400
Subject: [PATCH 18/19] Removed duplicate code
---
backend/app/api_views.py | 49 +---------------------------------------
1 file changed, 1 insertion(+), 48 deletions(-)
diff --git a/backend/app/api_views.py b/backend/app/api_views.py
index d0e48069..f9c55b59 100644
--- a/backend/app/api_views.py
+++ b/backend/app/api_views.py
@@ -1,6 +1,5 @@
import json
import random
-from math import ceil
from rest_framework import status
from rest_framework.decorators import api_view
@@ -13,7 +12,7 @@
from app.view_helpers import (
get_map_squares_by_arondissement,
get_arrondissement_geojson,
- tag_confidence
+ tag_confidence, tag_helper
)
from .models import (
@@ -50,52 +49,6 @@
]
-def tag_helper(tag_name, page=None):
- all_yolo_results = PhotoAnalysisResult.objects.filter(name='yolo_model')
-
- if not all_yolo_results.count():
- return []
-
- relevant_results = []
- print('yolo results here: ', len(all_yolo_results))
- for result in all_yolo_results:
- data = result.parsed_result()
- if tag_name in data['labels']:
- relevant_results.append(result)
-
- print('relevant results: ', len(relevant_results))
-
- # TODO(ra) Fix the results per page math... it looks like it's stepping
- # through src photo indexes
- results_per_page = 20
- result_count = len(relevant_results)
- page_count = ceil(result_count / results_per_page)
-
- if page:
- first_result = results_per_page * (page-1)
- last_result = first_result + results_per_page
- print(first_result, last_result)
- relevant_results_this_page = relevant_results[first_result:last_result]
- else:
- relevant_results_this_page = relevant_results
-
- print(relevant_results_this_page)
-
- # sort by confidence
- by_confidence = []
- for result in relevant_results_this_page:
- data = result.parsed_result()
- confidence = 0
- for box in data['boxes']:
- # an image may have several tag_name in labels, find greatest confidence
- if box['label'] == tag_name:
- confidence = max(confidence, box['confidence'])
- by_confidence.append((result, confidence))
-
- sorted_analysis_obj = sorted(by_confidence, key=lambda obj: obj[1], reverse=True)
- return [result[0].photo for result in sorted_analysis_obj], result_count, page_count
-
-
@api_view(['GET'])
def photo(request, map_square_number, folder_number, photo_number):
"""
From 3b40af893366400331a10ea88660dec0ce4508c6 Mon Sep 17 00:00:00 2001
From: JusticeV452 <55002917+JusticeV452@users.noreply.github.com>
Date: Wed, 26 Jun 2024 14:36:02 -0400
Subject: [PATCH 19/19] Update translation_db.py
---
backend/app/translation_db.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/backend/app/translation_db.py b/backend/app/translation_db.py
index aae32251..2aa943f3 100644
--- a/backend/app/translation_db.py
+++ b/backend/app/translation_db.py
@@ -1,5 +1,7 @@
-from django.utils.translation import gettext_lazy
from textwrap import dedent
+from django.utils.translation import gettext_lazy
+
+# pylint: disable=line-too-long
def _(text, dedent_text=True):
@@ -231,4 +233,4 @@ def translate_tag(tag, default=None):
},
# },
"description": _("This project is still under construction and contains student work, so there may be features that are currently incomplete or inaccurate.")
-}
\ No newline at end of file
+}