Skip to content

Commit

Permalink
Merge pull request #3758 from ProjectSidewalk/develop
Browse files Browse the repository at this point in the history
8.1.0
  • Loading branch information
misaugstad authored Dec 2, 2024
2 parents 7649b6d + 99f527d commit 3271d0a
Show file tree
Hide file tree
Showing 37 changed files with 575 additions and 378 deletions.
6 changes: 3 additions & 3 deletions app/controllers/AdminController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class AdminController @Inject() (implicit val env: Environment[User, SessionAuth
val user: User = request.identity.get
WebpageActivityTable.save(WebpageActivity(0, user.userId.toString, ipAddress, "Visit_Admin", timestamp))
}
Future.successful(Ok(views.html.admin.index("Project Sidewalk", request.identity)))
Future.successful(Ok(views.html.admin.index("Sidewalk - Admin", request.identity)))
} else {
Future.failed(new AuthenticationException("User is not an administrator"))
}
Expand All @@ -76,7 +76,7 @@ class AdminController @Inject() (implicit val env: Environment[User, SessionAuth
if (Messages("measurement.system") == "metric") AuditTaskTable.getDistanceAudited(userId) / 1000F
else AuditTaskTable.getDistanceAudited(userId) * METERS_TO_MILES
}
Future.successful(Ok(views.html.admin.user("Project Sidewalk", request.identity.get, user, auditedDistance)))
Future.successful(Ok(views.html.admin.user("Sidewalk - AdminUser", request.identity.get, user, auditedDistance)))
case _ => Future.failed(new NotFoundException("Username not found."))
}
} else {
Expand All @@ -98,7 +98,7 @@ class AdminController @Inject() (implicit val env: Environment[User, SessionAuth
def task(taskId: Int) = UserAwareAction.async { implicit request =>
if (isAdmin(request.identity)) {
AuditTaskTable.find(taskId) match {
case Some(task) => Future.successful(Ok(views.html.admin.task("Project Sidewalk", request.identity, task)))
case Some(task) => Future.successful(Ok(views.html.admin.task("Sidewalk - AdminTask", request.identity, task)))
case _ => Future.successful(Redirect("/"))
}
} else {
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/AttributeController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class AttributeController @Inject() (implicit val env: Environment[User, Session
*/
def index = UserAwareAction.async { implicit request =>
if (isAdmin(request.identity)) {
Future.successful(Ok(views.html.clustering("Project Sidewalk", request.identity)))
Future.successful(Ok(views.html.clustering("Sidewalk - Clustering", request.identity)))
} else {
Future.successful(Redirect("/"))
}
Expand Down
445 changes: 234 additions & 211 deletions app/controllers/AuditController.scala

Large diffs are not rendered by default.

157 changes: 102 additions & 55 deletions app/controllers/ValidationController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,41 +38,72 @@ class ValidationController @Inject() (implicit val env: Environment[User, Sessio
val validationMissionStr: String = "validation"

/**
* Returns the validation page.
* Returns /validate wrapper page.
*/
def validate = UserAwareAction.async { implicit request =>
def validateWrapper = UserAwareAction.async { implicit request =>
request.identity match {
case Some(user) =>
val adminParams = AdminValidateParams(adminVersion = false)
val r: UserAwareRequest[AnyContent] = request
val validationData = getDataForValidationPages(request, labelCount = 10, "Visit_Validate", adminParams)
if (validationData._4.missionType != "validation") {
Future.successful(Redirect("/explore"))
} else {
Future.successful(Ok(views.html.validation("Sidewalk - Validate", Some(user), adminParams, validationData._1, validationData._2, validationData._3, validationData._4.numComplete, validationData._5, validationData._6, validationData._7)))
}
Future.successful(Ok(views.html.validationWrapper("Sidewalk - Validate", Some(user))))
case None =>
Future.successful(Redirect(s"/anonSignUp?url=/validate"));
Future.successful(Redirect("/anonSignUp?url=/validate"))
}
}

/**
* Returns the new validation that includes severity and tags page.
*/
def newValidateBeta = UserAwareAction.async { implicit request =>
if (isAdmin(request.identity)) {
* Returns the validation page.
*/
def validate = UserAwareAction.async { implicit request =>
if (request.headers.get("Sec-Fetch-Dest").getOrElse("") == "document") {
validateWrapper.apply(request)
} else {
request.identity match {
case Some(user) =>
val adminParams = AdminValidateParams(adminVersion = false)
val validationData = getDataForValidationPages(request, labelCount = 10, "Visit_NewValidateBeta", adminParams)
val validationData = getDataForValidationPages(request, labelCount = 10, "Visit_Validate", adminParams)
if (validationData._4.missionType != "validation") {
Future.successful(Redirect("/explore"))
} else {
val tags: List[Tag] = TagTable.getTagsForCurrentCity
Future.successful(Ok(views.html.newValidateBeta("Sidewalk - NewValidateBeta", Some(user), adminParams, validationData._1, validationData._2, validationData._3, validationData._4.numComplete, validationData._5, validationData._6, tags)))
Future.successful(Ok(views.html.validation("Sidewalk - Validate", Some(user), adminParams, validationData._1, validationData._2, validationData._3, validationData._4.numComplete, validationData._5, validationData._6, validationData._7)))
}
case None =>
Future.successful(Redirect(s"/anonSignUp?url=/newValidateBeta"));
Future.successful(Redirect(s"/anonSignUp?url=/validate"));
}
}
}

/**
* Returns /newValidateBeta wrapper page.
*/
def newValidateBetaWrapper = UserAwareAction.async { implicit request =>
request.identity match {
case Some(user) =>
Future.successful(Ok(views.html.newValidateBetaWrapper("Sidewalk - NewValidateBeta", Some(user))))
case None =>
Future.successful(Redirect("/anonSignUp?url=/newValidateBeta"))
}
}

/**
* Returns the new validation that includes severity and tags page.
*/
def newValidateBeta = UserAwareAction.async { implicit request =>
if (isAdmin(request.identity)) {
if (request.headers.get("Sec-Fetch-Dest").getOrElse("") == "document") {
newValidateBetaWrapper.apply(request)
} else {
request.identity match {
case Some(user) =>
val adminParams = AdminValidateParams(adminVersion = false)
val validationData = getDataForValidationPages(request, labelCount = 10, "Visit_NewValidateBeta", adminParams)
if (validationData._4.missionType != "validation") {
Future.successful(Redirect("/explore"))
} else {
val tags: List[Tag] = TagTable.getTagsForCurrentCity
Future.successful(Ok(views.html.newValidateBeta("Sidewalk - NewValidateBeta", Some(user), adminParams, validationData._1, validationData._2, validationData._3, validationData._4.numComplete, validationData._5, validationData._6, tags)))
}
case None =>
Future.successful(Redirect(s"/anonSignUp?url=/newValidateBeta"));
}
}
} else {
Future.failed(new AuthenticationException("This is a beta currently only open to Admins."))
Expand All @@ -97,6 +128,18 @@ class ValidationController @Inject() (implicit val env: Environment[User, Sessio
}
}

/**
* Returns /adminValidate wrapper page.
*/
def adminValidationWrapper = UserAwareAction.async { implicit request =>
request.identity match {
case Some(user) =>
Future.successful(Ok(views.html.adminValidationWrapper("Sidewalk - AdminValidate", Some(user))))
case None =>
Future.successful(Redirect("/anonSignUp?url=/adminValidate"))
}
}

/**
* Returns an admin version of the validation page.
* @param labelType Label type or label type ID to validate.
Expand All @@ -105,43 +148,47 @@ class ValidationController @Inject() (implicit val env: Environment[User, Sessio
*/
def adminValidate(labelType: Option[String], users: Option[String], neighborhoods: Option[String]) = UserAwareAction.async { implicit request =>
if (isAdmin(request.identity)) {
// If any inputs are invalid, send back error message. For each input, we check if the input is an integer
// representing a valid ID (label_type_id, user_id, or region_id) or a String representing a valid name for that
// parameter (label_type, username, or region_name).
val possibleLabTypeIds: List[Int] = LabelTable.valLabelTypeIds
val parsedLabelTypeId: Option[Option[Int]] = labelType.map { lType =>
val parsedId: Try[Int] = Try(lType.toInt)
val lTypeIdFromName: Option[Int] = LabelTypeTable.labelTypeToId(lType)
if (parsedId.isSuccess && possibleLabTypeIds.contains(parsedId.get)) parsedId.toOption
else if (lTypeIdFromName.isDefined) lTypeIdFromName
else None
}
val userIdsList: Option[List[Option[String]]] = users.map(_.split(',').map(_.trim).map { userStr =>
val parsedUserId: Option[UUID] = Try(UUID.fromString(userStr)).toOption
val user: Option[DBUser] = parsedUserId.flatMap(u => UserTable.findById(u))
val userId: Option[String] = UserTable.find(userStr).map(_.userId)
if (user.isDefined) Some(userStr) else if (userId.isDefined) Some(userId.get) else None
}.toList)
val neighborhoodIdList: Option[List[Option[Int]]] = neighborhoods.map(_.split(",").map { regionStr =>
val parsedRegionId: Try[Int] = Try(regionStr.toInt)
val regionFromName: Option[Region] = RegionTable.getRegionByName(regionStr)
if (parsedRegionId.isSuccess && RegionTable.getRegion(parsedRegionId.get).isDefined) parsedRegionId.toOption
else if (regionFromName.isDefined) regionFromName.map(_.regionId)
else None
}.toList)

// If any inputs are invalid (even any item in the list of users/regions), send back error message.
if (parsedLabelTypeId.isDefined && parsedLabelTypeId.get.isEmpty) {
Future.successful(BadRequest(s"Invalid label type provided: ${labelType.get}. Valid label types are: ${LabelTypeTable.getAllLabelTypes.filter(l => possibleLabTypeIds.contains(l.labelTypeId)).map(_.labelType).toList.reverse.mkString(", ")}. Or you can use their IDs: ${possibleLabTypeIds.mkString(", ")}."))
} else if (userIdsList.isDefined && userIdsList.get.length != userIdsList.get.flatten.length) {
Future.successful(BadRequest(s"One or more of the users provided were not found; please double check your list of users! You can use either their usernames or user IDs. You provided: ${users.get}"))
} else if (neighborhoodIdList.isDefined && neighborhoodIdList.get.length != neighborhoodIdList.get.flatten.length) {
Future.successful(BadRequest(s"One or more of the neighborhoods provided were not found; please double check your list of neighborhoods! You can use either their names or IDs. You provided: ${neighborhoods.get}"))
if (request.headers.get("Sec-Fetch-Dest").getOrElse("") == "document") {
adminValidationWrapper.apply(request)
} else {
// If all went well, load the data for Admin Validate with the specified filters.
val adminParams: AdminValidateParams = AdminValidateParams(adminVersion = true, parsedLabelTypeId.flatten, userIdsList.map(_.flatten), neighborhoodIdList.map(_.flatten))
val validationData = getDataForValidationPages(request, labelCount=10, "Visit_AdminValidate", adminParams)
Future.successful(Ok(views.html.validation("Sidewalk - Admin Validate", request.identity, adminParams, validationData._1, validationData._2, validationData._3, validationData._4.numComplete, validationData._5, validationData._6, validationData._7)))
// If any inputs are invalid, send back error message. For each input, we check if the input is an integer
// representing a valid ID (label_type_id, user_id, or region_id) or a String representing a valid name for that
// parameter (label_type, username, or region_name).
val possibleLabTypeIds: List[Int] = LabelTable.valLabelTypeIds
val parsedLabelTypeId: Option[Option[Int]] = labelType.map { lType =>
val parsedId: Try[Int] = Try(lType.toInt)
val lTypeIdFromName: Option[Int] = LabelTypeTable.labelTypeToId(lType)
if (parsedId.isSuccess && possibleLabTypeIds.contains(parsedId.get)) parsedId.toOption
else if (lTypeIdFromName.isDefined) lTypeIdFromName
else None
}
val userIdsList: Option[List[Option[String]]] = users.map(_.split(',').map(_.trim).map { userStr =>
val parsedUserId: Option[UUID] = Try(UUID.fromString(userStr)).toOption
val user: Option[DBUser] = parsedUserId.flatMap(u => UserTable.findById(u))
val userId: Option[String] = UserTable.find(userStr).map(_.userId)
if (user.isDefined) Some(userStr) else if (userId.isDefined) Some(userId.get) else None
}.toList)
val neighborhoodIdList: Option[List[Option[Int]]] = neighborhoods.map(_.split(",").map { regionStr =>
val parsedRegionId: Try[Int] = Try(regionStr.toInt)
val regionFromName: Option[Region] = RegionTable.getRegionByName(regionStr)
if (parsedRegionId.isSuccess && RegionTable.getRegion(parsedRegionId.get).isDefined) parsedRegionId.toOption
else if (regionFromName.isDefined) regionFromName.map(_.regionId)
else None
}.toList)

// If any inputs are invalid (even any item in the list of users/regions), send back error message.
if (parsedLabelTypeId.isDefined && parsedLabelTypeId.get.isEmpty) {
Future.successful(BadRequest(s"Invalid label type provided: ${labelType.get}. Valid label types are: ${LabelTypeTable.getAllLabelTypes.filter(l => possibleLabTypeIds.contains(l.labelTypeId)).map(_.labelType).toList.reverse.mkString(", ")}. Or you can use their IDs: ${possibleLabTypeIds.mkString(", ")}."))
} else if (userIdsList.isDefined && userIdsList.get.length != userIdsList.get.flatten.length) {
Future.successful(BadRequest(s"One or more of the users provided were not found; please double check your list of users! You can use either their usernames or user IDs. You provided: ${users.get}"))
} else if (neighborhoodIdList.isDefined && neighborhoodIdList.get.length != neighborhoodIdList.get.flatten.length) {
Future.successful(BadRequest(s"One or more of the neighborhoods provided were not found; please double check your list of neighborhoods! You can use either their names or IDs. You provided: ${neighborhoods.get}"))
} else {
// If all went well, load the data for Admin Validate with the specified filters.
val adminParams: AdminValidateParams = AdminValidateParams(adminVersion = true, parsedLabelTypeId.flatten, userIdsList.map(_.flatten), neighborhoodIdList.map(_.flatten))
val validationData = getDataForValidationPages(request, labelCount = 10, "Visit_AdminValidate", adminParams)
Future.successful(Ok(views.html.validation("Sidewalk - Admin Validate", request.identity, adminParams, validationData._1, validationData._2, validationData._3, validationData._4.numComplete, validationData._5, validationData._6, validationData._7)))
}
}
} else {
Future.failed(new AuthenticationException("User is not an administrator"))
Expand Down
2 changes: 1 addition & 1 deletion app/models/label/LabelTable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ object LabelTable {
|INNER JOIN label_type ON label.label_type_id = label_type.label_type_id
|WHERE (time_created AT TIME ZONE 'US/Pacific') > (now() AT TIME ZONE 'US/Pacific') - interval '168 hours'
| AND label.deleted = false
| AND label_type.label_type = $labelType;""".stripMargin
| AND label_type.label_type = '$labelType';""".stripMargin
)
countQuery.first
}
Expand Down
11 changes: 11 additions & 0 deletions app/views/adminValidationWrapper.scala.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@import models.user.User
@(title: String, user: Option[User] = None)(implicit lang: Lang)

@main(title, Some("/validate")) {
@navbar(user, Some("/validate"))
<link rel="stylesheet" href='@routes.Assets.at("stylesheets/wrapperFrame.css")'/>

<iframe id="wrapper-frame"></iframe>

<script type="text/javascript" src='@routes.Assets.at("javascripts/common/wrapperFrame.js")'></script>
}
6 changes: 0 additions & 6 deletions app/views/explore.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@
@currentCity = @{cityInfo.filter(c => c.current).head}

@main(title, Some("/explore")) {
@if(userRoute.isDefined) {
@navbar(user, Some(s"/explore?routeId=${userRoute.get.routeId}&resumeRoute=true"))
} else {
@navbar(user, Some("/explore"))
}

<link rel="stylesheet" href='@routes.Assets.at("javascripts/SVLabel/build/SVLabel.css")'/>
<link rel="stylesheet" href='@routes.Assets.at("stylesheets/animate.css")'/>

Expand Down
11 changes: 11 additions & 0 deletions app/views/exploreWrapper.scala.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@import models.user.User
@(title: String, user: Option[User] = None)(implicit lang: Lang)

@main(title, Some("/explore")) {
@navbar(user, Some("/explore"))
<link rel="stylesheet" href='@routes.Assets.at("stylesheets/wrapperFrame.css")'/>

<iframe id="wrapper-frame"></iframe>

<script type="text/javascript" src='@routes.Assets.at("javascripts/common/wrapperFrame.js")'></script>
}
2 changes: 1 addition & 1 deletion app/views/forgotPassword.scala.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@(forgotPasswordForm: Form[String])(implicit request: RequestHeader, lang: Lang)
@import views.html.bootstrap._

@main("Project Sidewalk - Recover Password") {
@main("Sidewalk - Recover Password") {
@navbar(None)
@request.flash.get("error").map { msg =>
<div class="col-md-6 col-md-offset-3 alert alert-danger alert-error"
Expand Down
2 changes: 1 addition & 1 deletion app/views/gallery.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
@(title: String, user: Option[User] = None, cityInfo: List[CityInfo], labelType: String, labels: List[(String, String)], regionIds: List[Int], severities: List[Int], tags: List[String], valOptions: List[String])(implicit lang: Lang)
@currentCity = @{cityInfo.filter(c => c.current).head}

@main(title) {
@main(title, Some("/gallery")) {
<script type="text/javascript" src='@routes.Assets.at("javascripts/Gallery/build/Gallery.js")'></script>
<script type="text/javascript" src='@routes.Assets.at("javascripts/lib/i18next-23.14.0.min.js")'></script>
<script type="text/javascript" src='@routes.Assets.at("javascripts/lib/i18nextHttpBackend-2.6.0.min.js")'></script>
Expand Down
2 changes: 1 addition & 1 deletion app/views/main.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
document.getElementsByTagName("body")[0].style.overflow = "hidden";
</script>
}
<!-- Trying out no footer on Explore or Validate. Mini footer on mobile sign in/up. Code is weird bc "else if" doesn't work in template scala rn. -->
<!-- No footer on Explore or Validate. Mini footer on mobile sign in/up. Code is weird bc "else if" doesn't work in template scala rn. -->
@if(url.get == "/explore" || url.get == "/validate" || url.get == "/newValidateBeta" || url.get == "/signInMobile" || url.get == "/signUpMobile") {
@if(url.get == "/explore" || url.get == "/validate" || url.get == "/newValidateBeta") {
} else {
Expand Down
2 changes: 0 additions & 2 deletions app/views/newValidateBeta.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
@(title: String, user: Option[User] = None, adminParams: AdminValidateParams, mission: Option[JsValue], labelList: Option[JsValue], progress: Option[JsValue], missionSetProgress: Int, hasNextMission: Boolean, completedValidations: Int, tagList: List[Tag])(implicit lang: Lang)

@main(title, Some("/newValidateBeta")) {
@navbar(user, Some("/newValidateBeta"))

@icons()

<link rel="stylesheet" href='@routes.Assets.at("stylesheets/animate.css")'/>
Expand Down
11 changes: 11 additions & 0 deletions app/views/newValidateBetaWrapper.scala.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@import models.user.User
@(title: String, user: Option[User] = None)(implicit lang: Lang)

@main(title, Some("/newValidateBeta")) {
@navbar(user, Some("/newValidateBeta"))
<link rel="stylesheet" href='@routes.Assets.at("stylesheets/wrapperFrame.css")'/>

<iframe id="wrapper-frame"></iframe>

<script type="text/javascript" src='@routes.Assets.at("javascripts/common/wrapperFrame.js")'></script>
}
2 changes: 1 addition & 1 deletion app/views/resetPassword.scala.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@(resetPasswordForm: Form[forms.ResetPasswordForm.PasswordData], token: java.util.UUID)(implicit request: RequestHeader, lang: Lang)
@import views.html.bootstrap._

@main("Project Sidewalk - Reset Password") {
@main("Sidewalk - Reset Password") {
@navbar(None)
@request.flash.get("error").map { msg =>
<div class="col-md-6 col-md-offset-3 alert alert-danger alert-error"
Expand Down
2 changes: 1 addition & 1 deletion app/views/signIn.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

@import views.html.bootstrap._

@main("Project Sidewalk - Sign In") {
@main("Sidewalk - Sign In") {
@navbar(None, Some("/signIn"))
@request.flash.get("success").map { msg =>
<div class="col-md-6 col-md-offset-3 alert alert-success"
Expand Down
Loading

0 comments on commit 3271d0a

Please sign in to comment.