Skip to content

Commit

Permalink
Merge pull request #3653 from ProjectSidewalk/develop
Browse files Browse the repository at this point in the history
v7.20.6
  • Loading branch information
misaugstad authored Sep 13, 2024
2 parents bb9cde5 + 1047beb commit 2c1191f
Show file tree
Hide file tree
Showing 19 changed files with 122 additions and 32 deletions.
4 changes: 2 additions & 2 deletions app/controllers/LabelController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ class LabelController @Inject() (implicit val env: Environment[User, SessionAuth
"cameraPitch" -> label.cameraPitch,
"panoWidth" -> label.panoWidth,
"panoHeight" -> label.panoHeight,
// TODO Simplify this after removing the `tag` table.
"tagIds" -> label.labelData.tags.flatMap(t => allTags.filter(at => at.tag == t && Some(at.labelTypeId) == LabelTypeTable.labelTypeToId(label.labelType)).map(_.tagId).headOption),
"severity" -> label.labelData.severity,
"tutorial" -> label.labelData.tutorial,
Expand Down Expand Up @@ -79,7 +78,8 @@ class LabelController @Inject() (implicit val env: Environment[User, SessionAuth
Future.successful(Ok(JsArray(tags.map { tag => Json.obj(
"tag_id" -> tag.tagId,
"label_type" -> LabelTypeTable.labelTypeIdToLabelType(tag.labelTypeId).get,
"tag" -> tag.tag
"tag" -> tag.tag,
"mutually_exclusive_with" -> tag.mutuallyExclusiveWith
)})))
}
}
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/TaskController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ class TaskController @Inject() (implicit val env: Environment[User, SessionAuthe
// Map tag IDs to their string representations.
val tagStrings: List[String] = label.tagIds.distinct.flatMap(t => TagTable.selectAllTags.filter(_.tagId == t).map(_.tag).headOption).toList

LabelTable.update(existingLab.labelId, label.deleted, label.severity, label.temporary, label.description, tagStrings)
LabelTable.updateFromExplore(existingLab.labelId, label.deleted, label.severity, label.temporary, label.description, tagStrings)
existingLab.labelId
}
case None =>
Expand Down
3 changes: 2 additions & 1 deletion app/formats/json/LabelFormat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ object LabelFormat {
implicit val tagWrites: Writes[Tag] = (
(__ \ "tag_id").write[Int] and
(__ \ "label_type_id").write[Int] and
(__ \ "tag_name").write[String]
(__ \ "tag_name").write[String] and
(__ \ "mutually_exclusive_with").writeNullable[String]
)(unlift(Tag.unapply))
}
16 changes: 7 additions & 9 deletions app/models/label/LabelTable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import models.utils.MyPostgresDriver
import models.utils.MyPostgresDriver.simple._
import models.utils.CommonUtils.ordered
import models.validation.ValidationTaskCommentTable
import org.joda.time.{DateTime, DateTimeZone}
import play.api.Play
import play.api.Play.current
import play.api.libs.json.{JsObject, Json}
Expand All @@ -29,8 +28,6 @@ import java.time.Instant
import scala.collection.mutable.ListBuffer
import scala.slick.jdbc.{GetResult, StaticQuery => Q}
import scala.slick.lifted.ForeignKeyQuery
import java.time.LocalDateTime
import java.net.{HttpURLConnection, URL}

case class Label(labelId: Int, auditTaskId: Int, missionId: Int, userId: String, gsvPanoramaId: String,
labelTypeId: Int, deleted: Boolean, temporaryLabelId: Int, timeCreated: Timestamp, tutorial: Boolean,
Expand Down Expand Up @@ -373,7 +370,7 @@ object LabelTable {
}

/**
* Update the metadata that users might change after initially placing the label.
* Update the metadata that users might change on the Explore page after initially placing the label.
*
* @param labelId
* @param deleted
Expand All @@ -383,7 +380,7 @@ object LabelTable {
* @param tags
* @return
*/
def update(labelId: Int, deleted: Boolean, severity: Option[Int], temporary: Boolean, description: Option[String], tags: List[String]): Int = db.withTransaction { implicit session =>
def updateFromExplore(labelId: Int, deleted: Boolean, severity: Option[Int], temporary: Boolean, description: Option[String], tags: List[String]): Int = db.withTransaction { implicit session =>
val labelToUpdateQuery = labelsUnfiltered.filter(_.labelId === labelId)
val labelToUpdate: Label = labelToUpdateQuery.first
val cleanedTags: List[String] = TagTable.cleanTagList(tags, labelToUpdate.labelTypeId)
Expand Down Expand Up @@ -418,6 +415,7 @@ object LabelTable {
def updateAndSaveHistory(labelId: Int, severity: Option[Int], tags: List[String], userId: String, source: String, labelValidationId: Int): Int = db.withTransaction { implicit session =>
val labelToUpdateQuery = labelsUnfiltered.filter(_.labelId === labelId)
val labelToUpdate: Option[Label] = labelToUpdateQuery.firstOption
// TODO do we need to pass session object to this function? https://github.com/ProjectSidewalk/SidewalkWebpage/issues/3550
val cleanedTags: Option[List[String]] = labelToUpdate.map(l => TagTable.cleanTagList(tags, l.labelTypeId))

// If there is an actual change to the label, update it and add to the label_history table. O/w update nothing.
Expand All @@ -430,7 +428,7 @@ object LabelTable {
}

/**
* Updates the label and label_history tables appropriately when a validation is deleted (using the back button)
* Updates the label and label_history tables appropriately when a validation is deleted (using the back button).
*
* If the given validation represents the most recent change to the label, undo this validation's change in the label
* table and delete this validation. If there have been subsequent changes to the label, just delete this validation.
Expand Down Expand Up @@ -474,11 +472,11 @@ object LabelTable {
* Saves a new label in the table.
*/
def save(label: Label): Int = db.withSession { implicit session =>
require(label.tags.length == label.tags.distinct.length, "List of tags must be unique.")
val labelId: Int = (labelsUnfiltered returning labelsUnfiltered.map(_.labelId)) += label
val cleanLabel: Label = label.copy(tags = TagTable.cleanTagList(label.tags, label.labelTypeId))
val labelId: Int = (labelsUnfiltered returning labelsUnfiltered.map(_.labelId)) += cleanLabel

// Add a corresponding entry to the label_history table.
LabelHistoryTable.save(LabelHistory(0, labelId, label.severity, label.tags, label.userId, label.timeCreated, "Explore", None))
LabelHistoryTable.save(LabelHistory(0, labelId, cleanLabel.severity, cleanLabel.tags, cleanLabel.userId, cleanLabel.timeCreated, "Explore", None))

labelId
}
Expand Down
36 changes: 29 additions & 7 deletions app/models/label/TagTable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,26 @@ package models.label

import models.attribute.ConfigTable
import models.utils.MyPostgresDriver.simple._
import play.api.Logger
import play.api.Play.current
import play.api.cache.Cache
import scala.concurrent.duration.DurationInt
import scala.slick.lifted.ForeignKeyQuery
import scala.slick.lifted.{ForeignKeyQuery, Index}

case class Tag(tagId: Int, labelTypeId: Int, tag: String)
case class Tag(tagId: Int, labelTypeId: Int, tag: String, mutuallyExclusiveWith: Option[String])

class TagTable(tagParam: slick.lifted.Tag) extends Table[Tag](tagParam, "tag") {
def tagId: Column[Int] = column[Int]("tag_id", O.PrimaryKey, O.AutoInc)
def labelTypeId: Column[Int] = column[Int]("label_type_id")
def tag: Column[String] = column[String]("tag")
def mutuallyExclusiveWith: Column[Option[String]] = column[Option[String]]("mutually_exclusive_with")

def * = (tagId, labelTypeId, tag) <> ((Tag.apply _).tupled, Tag.unapply)
def * = (tagId, labelTypeId, tag, mutuallyExclusiveWith) <> ((Tag.apply _).tupled, Tag.unapply)

def labelType: ForeignKeyQuery[LabelTypeTable, LabelType] =
foreignKey("tag_label_type_id_fkey", labelTypeId, TableQuery[LabelTypeTable])(_.labelTypeId)

def labelTypeTagUnique: Index = index("tag_label_type_id_tag_unique", (labelTypeId, tag), unique = true)
}

object TagTable {
Expand All @@ -40,6 +44,12 @@ object TagTable {
}
}

def selectTagsByLabelTypeId(labelTypeId: Int): List[Tag] = db.withSession { implicit session =>
Cache.getOrElse(s"selectTagsByLabelTypeId($labelTypeId)") {
tagTable.filter(_.labelTypeId === labelTypeId).list
}
}

def selectTagsByLabelType(labelType: String): List[Tag] = db.withSession { implicit session =>
Cache.getOrElse(s"selectTagsByLabelType($labelType)") {
tagTable
Expand All @@ -50,12 +60,24 @@ object TagTable {
}

def cleanTagList(tags: List[String], labelTypeId: Int): List[String] = {
val labelType: String = LabelTypeTable.labelTypeIdToLabelType(labelTypeId).get
cleanTagList(tags, labelType)
val validTags: List[String] = selectTagsByLabelTypeId(labelTypeId).map(_.tag)
val cleanedTags: List[String] = tags.map(_.toLowerCase).distinct.filter(t => validTags.contains(t))
val conflictingTags: List[String] = findConflictingTags(cleanedTags.toSet, labelTypeId)
if (conflictingTags.nonEmpty) {
Logger.warn(s"Tag list contains conflicting tags, removing all that conflict: ${conflictingTags.mkString(", ")}")
cleanedTags.filterNot(conflictingTags.contains)
} else {
cleanedTags
}
}

def cleanTagList(tags: List[String], labelType: String): List[String] = {
val validTags = selectTagsByLabelType(labelType).map(_.tag)
tags.map(_.toLowerCase).distinct.filter(t => validTags.contains(t))
val labelTypeId: Int = LabelTypeTable.labelTypeToId(labelType).get
cleanTagList(tags, labelTypeId)
}

def findConflictingTags(tags: Set[String], labelTypeId: Int): List[String] = {
val allTags: List[Tag] = selectTagsByLabelTypeId(labelTypeId)
allTags.filter(tag => tags.contains(tag.tag) && tag.mutuallyExclusiveWith.exists(tags.contains)).map(_.tag)
}
}
2 changes: 1 addition & 1 deletion app/models/utils/Configs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ object Configs {
* Returns list of info for all cities, including formatted names (in current language), URL, visibility.
*/
def getAllCityInfo(lang: Lang): List[CityInfo] = {
Cache.getOrElse("getAllCityInfo()") {
Cache.getOrElse(s"getAllCityInfo($lang)") {
val currentCityId: String = Play.configuration.getString("city-id").get
val currentCountryId: String = Play.configuration.getString(s"city-params.country-id.$currentCityId").get
val envType: String = Play.configuration.getString("environment-type").get
Expand Down
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import play.PlayScala

name := """sidewalk-webpage"""

version := "7.20.5"
version := "7.20.6"

scalaVersion := "2.10.7"

Expand Down
23 changes: 23 additions & 0 deletions conf/cityparams.conf
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,15 @@ city-params {
"teaneck-nj"
"walla-walla-wa"
"st-louis-mo"
"la-ca"
"mendota-il"
]
city-short-name {
washington-dc = "DC"
cdmx = "CDMX"
spgg = "SPGG"
validation-study = "Val Study"
la-ca = "LA"
}
state-id {
newberg-or = "oregon"
Expand All @@ -47,6 +50,8 @@ city-params {
teaneck-nj = "new-jersey"
walla-walla-wa = "washington"
st-louis-mo = "missouri"
la-ca = "california"
mendota-il = "illinois"
}
country-id {
newberg-or = "usa"
Expand All @@ -72,6 +77,8 @@ city-params {
teaneck-nj = "usa"
walla-walla-wa = "usa"
st-louis-mo = "usa"
la-ca = "usa"
mendota-il = "usa"
}
status {
newberg-or = "public"
Expand All @@ -97,6 +104,8 @@ city-params {
teaneck-nj = "public"
walla-walla-wa = "private"
st-louis-mo = "public"
la-ca = "private"
mendota-il = "public"
}
launch-date {
newberg-or = "2019-01-31"
Expand All @@ -121,6 +130,8 @@ city-params {
teaneck-nj = "2023-08-24"
walla-walla-wa = "2023-10-05"
st-louis-mo = "2024-4-10"
la-ca = "2024-9-16"
mendota-il = "2024-9-16"
}
skyline-img = {
newberg-or = "skyline1.png"
Expand All @@ -146,6 +157,8 @@ city-params {
teaneck-nj = "skyline1.png"
walla-walla-wa = "skyline1.png"
st-louis-mo = "skyline1.png"
la-ca = "skyline1.png"
mendota-il = "skyline1.png"
}
logo-img = {
newberg-or = "sidewalk-logo.png"
Expand All @@ -171,6 +184,8 @@ city-params {
teaneck-nj = "sidewalk-logo.png"
walla-walla-wa = "sidewalk-logo.png"
st-louis-mo = "sidewalk-logo.png"
la-ca = "sidewalk-logo.png"
mendota-il = "sidewalk-logo.png"
}
landing-page-url {
prod {
Expand All @@ -197,6 +212,8 @@ city-params {
teaneck-nj = "https://sidewalk-teaneck.cs.washington.edu"
walla-walla-wa = "https://sidewalk-walla-walla.cs.washington.edu"
st-louis-mo = "https://sidewalk-st-louis.cs.washington.edu"
la-ca = "https://sidewalk-la.cs.washington.edu"
mendota-il = "https://sidewalk-mendota.cs.washington.edu"
}
test {
newberg-or = "https://sidewalk-newberg-test.cs.washington.edu"
Expand All @@ -222,6 +239,8 @@ city-params {
teaneck-nj = "https://sidewalk-teaneck-test.cs.washington.edu"
walla-walla-wa = "https://sidewalk-walla-walla-test.cs.washington.edu"
st-louis-mo = "https://sidewalk-st-louis-test.cs.washington.edu"
la-ca = "https://sidewalk-la-test.cs.washington.edu"
mendota-il = "https://sidewalk-mendota-test.cs.washington.edu"
}
}
google-analytics-4-id {
Expand Down Expand Up @@ -249,6 +268,8 @@ city-params {
teaneck-nj = "G-2RZB03K3HW"
walla-walla-wa = "G-RGCXF4KYED"
st-louis-mo = "G-3HL22FM4BS"
la-ca = "G-815WLSJ888"
mendota-il = "G-1CYXWS6195"
}
test {
newberg-or = "G-P2JPSFFN3H"
Expand All @@ -273,6 +294,8 @@ city-params {
teaneck-nj = "G-611R79E2SJ"
walla-walla-wa = "G-7BWV5VRENW"
st-louis-mo = "G-DJMP9QBM0M"
la-ca = "G-LJKNZP9DYK"
mendota-il = "G-2V84GVCHV4"
}
}
// New cities have ony GA 4. Old cities also retain the old GA tracking.
Expand Down
5 changes: 5 additions & 0 deletions conf/evolutions/default/244.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# --- !Ups
UPDATE mission_type SET mission_type_id = 7 WHERE mission_type = 'labelmapValidation';
ALTER TABLE label_history OWNER TO sidewalk;

# --- !Downs
21 changes: 21 additions & 0 deletions conf/evolutions/default/245.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# --- !Ups
-- No mutually exclusive tags exist together in a prod database, so we don't need to clean existing data.
ALTER TABLE tag
ADD CONSTRAINT tag_label_type_id_tag_unique UNIQUE (label_type_id, tag),
ADD COLUMN mutually_exclusive_with TEXT,
ADD CONSTRAINT tag_mutually_exclusive_with_self_reference_check CHECK (mutually_exclusive_with IS DISTINCT FROM tag);

UPDATE tag SET mutually_exclusive_with = 'tactile warning' WHERE tag = 'missing tactile warning';
UPDATE tag SET mutually_exclusive_with = 'missing tactile warning' WHERE tag = 'tactile warning';
UPDATE tag SET mutually_exclusive_with = 'no alternate route' WHERE tag = 'alternate route present';
UPDATE tag SET mutually_exclusive_with = 'alternate route present' WHERE tag = 'no alternate route';
UPDATE tag SET mutually_exclusive_with = 'street has no sidewalks' WHERE tag = 'street has a sidewalk';
UPDATE tag SET mutually_exclusive_with = 'street has a sidewalk' WHERE tag = 'street has no sidewalks';
UPDATE tag SET mutually_exclusive_with = 'two buttons' WHERE tag = 'one button';
UPDATE tag SET mutually_exclusive_with = 'one button' WHERE tag = 'two buttons';

# --- !Downs
ALTER TABLE tag
DROP CONSTRAINT IF EXISTS tag_mutually_exclusive_with_self_reference_check,
DROP COLUMN mutually_exclusive_with,
DROP CONSTRAINT IF EXISTS tag_label_type_id_tag_unique;
5 changes: 5 additions & 0 deletions conf/evolutions/default/246.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# --- !Ups
INSERT INTO version VALUES ('7.20.6', now(), 'Fixes conflicting tags but in new Validate, adds LA & Mendota configs.');

# --- !Downs
DELETE FROM version WHERE version_id = '7.20.6';
3 changes: 3 additions & 0 deletions conf/messages
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ city.name.burnaby = Burnaby
city.name.teaneck-nj = Teaneck
city.name.walla-walla-wa = Walla Walla
city.name.st-louis-mo = St. Louis
city.name.la-ca = Los Angeles
city.name.mendota-il = Mendota

state.name.oregon = Oregon
state.name.dc = DC
Expand All @@ -37,6 +39,7 @@ state.name.pennsylvania = Pennsylvania
state.name.illinois = Illinois
state.name.new-jersey = New Jersey
state.name.missouri = Missouri
state.name.california = California

country.name.usa = USA
country.name.mexico = Mexico
Expand Down
2 changes: 2 additions & 0 deletions conf/messages.de
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ city.name.zurich = Zürich
city.name.taipei = Taipeh
city.name.new-taipei-tw = Neu-Taipeh

state.name.california = Kalifornien

country.name.usa = USA
country.name.mexico = Mexiko
country.name.netherlands = Niederlande
Expand Down
3 changes: 2 additions & 1 deletion conf/messages.es
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ city.state = {0}, {1}
city.name.cdmx = Ciudad de México
city.name.zurich = Zúrich
city.name.new-taipei-tw = Nuevo Taipei
city.name.st-louis = San Luis
city.name.st-louis-mo = San Luis
city.name.la-ca = Los Ángeles

state.name.oregon = Oregón
state.name.pennsylvania = Pensilvania
Expand Down
7 changes: 1 addition & 6 deletions conf/messages.nl
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,7 @@ city.state = {0}, {1}
city.name.cdmx = Mexico Stad
city.name.new-taipei-tw = Nieuw Taipei

state.name.oregon = Oregon
state.name.washington = Washington
state.name.ohio = Ohio
state.name.pennsylvania = Pennsylvania
state.name.illinois = Illinois
state.name.new-jersey = New Jersey
state.name.california = Californië

country.name.usa = USA
country.name.netherlands = Nederland
Expand Down
Loading

0 comments on commit 2c1191f

Please sign in to comment.