Setting state in ajax success in scalajs-react - scala.js

I am trying to open one popup on successful submission of another in scalajs-react. My problem is on success state is not getting modified. Here is my addNewAgent method called as a callback on submission of first popup.
def addNewAgent(userModel: UserModel, addNewAgent: Boolean = false): Callback = {
println(addNewAgent)
if(addNewAgent){
createUser(userModel).onComplete {
case Success(s) =>
println(s.msgType)
if (s.msgType == ApiResponseMsg.CreateUserWaiting){
t.modState(s => s.copy(showNewAgentForm = false, showConfirmAccountCreation = true))
} else {
t.modState(s => s.copy(showNewAgentForm = false, showRegistrationFailed = true))
}
case Failure(s) =>
println(s)
t.modState(s => s.copy(showRegistrationFailed = true))
// now you need to refresh the UI
}
t.modState(s => s.copy(showNewAgentForm = false))
} else {
t.modState(s => s.copy(showNewAgentForm = false))
}
}
and component code is :
val component = ReactComponentB[Props]("AddNewAgent")
.initialState(State()) // initial state from TodoStore
.backend(new Backend(_))
.renderPS(($, P, S) => {
val B = $.backend
<.div()(
Button(Button.Props(B.addNewAgentForm(), CommonStyle.default, Seq(HeaderCSS.Style.SignUpBtn)),"Sign Up"),
if (S.showNewAgentForm) NewAgentForm(NewAgentForm.Props(B.addNewAgent))
else if (S.showConfirmAccountCreation ) ConfirmAccountCreation(ConfirmAccountCreation.Props(B.confirmAccountCreation))
else
Seq.empty[ReactElement]
)
})
// .componentDidMount(scope => scope.backend.mounted(scope.props))
.configure(OnUnmount.install)
.build
def apply(props: Props) = component(props)

For anyone looking for an answer to this problem what is happening here is that
the modState calls inside the future completion will never be really called
because they return a Callback that don't run. To solve this you need to add runNow() like t.modState(s => s.copy(showNewAgentForm = false, showRegistrationFailed = true)).runNow()

Related

I am very close to finish my to do list application but there is a slight error

This is a to-do list application that i made as a beginner. However, there is an error that says missing parameter type in this line of code:
todoTable.selectionModel().selectedItem.onChange(
(_, newValue) => showTodoDetails(Some(newValue))
)
I can't figure out what the problem is as I had no issue running with it earlier. And it also seems to be the only error that keeps me from finishing the to-do application program.
Below is the file that is having an error
package ch.makery.address.view
import ch.makery.address.model.Todo
import ch.makery.address.MainApp
import scalafx.scene.control.{Alert, Label, TableColumn, TableView}
import scalafxml.core.macros.sfxml
import scalafx.beans.property.StringProperty
import scala.util.{Failure, Success}
import scalafx.Includes._
import scalafx.event.ActionEvent
import scalafx.scene.control.Alert.AlertType
#sfxml
class TodoOverviewController(
private val todoTable : TableView[Todo],
private val titleColumn : TableColumn[Todo, String],
private val titleLabel : Label,
private val descriptionLabel : Label
) {
// initialize Table View display contents model
todoTable.items = MainApp.todoData
// initialize columns's cell values
titleColumn.cellValueFactory = {_.value.title}
showTodoDetails(None);
todoTable.selectionModel().selectedItem.onChange(
(_, newValue) => showTodoDetails(Some(newValue))
)
private def showTodoDetails (todo : Option[Todo]) = {
todo match {
case Some(todo) =>
// Fill the labels with info from the todo object.
titleLabel.text <== todo.title
descriptionLabel.text <== todo.description
case None =>
// todo is null, remove all the text.
titleLabel.text = ""
descriptionLabel.text = ""
}
}
def handleNewTodo(action : ActionEvent) = {
val todo = new Todo("")
val okClicked = MainApp.showTodoEditDialog(todo);
if (okClicked) {
todo.save() match {
case Success(x) =>
MainApp.todoData += todo
case Failure(e) =>
val alert = new Alert(Alert.AlertType.Warning) {
initOwner(MainApp.stage)
title = "Failed to Save"
headerText = "Database Error"
contentText = "Database problem filed to save changes"
}.showAndWait()
}
}
}
def handleEditTodo(action : ActionEvent) = {
val selectedTodo = todoTable.selectionModel().selectedItem.value
if (selectedTodo != null) {
val okClicked = MainApp.showTodoEditDialog(selectedTodo)
if (okClicked) {
selectedTodo.save() match {
case Success(x) =>
showTodoDetails(Some(selectedTodo))
case Failure(e) =>
val alert = new Alert(Alert.AlertType.Warning) {
initOwner(MainApp.stage)
title = "Failed to Save"
headerText = "Database Error"
contentText = "Database problem filed to save changes"
}.showAndWait()
}
}
} else {
// Nothing selected.
val alert = new Alert(Alert.AlertType.Warning){
initOwner(MainApp.stage)
title = "No Selection"
headerText = "No Todo Selected"
contentText = "Please select a todo in the table."
}.showAndWait()
}
}
def handleDeleteTodo(action : ActionEvent) = {
val selectedIndex = todoTable.selectionModel().selectedIndex.value
val selectedTodo = todoTable.selectionModel().selectedItem.value
if (selectedIndex >= 0) {
selectedTodo.save() match {
case Success(x) =>
todoTable.items().remove(selectedIndex);
case Failure(e) =>
val alert = new Alert(Alert.AlertType.Warning) {
initOwner(MainApp.stage)
title = "Failed to Save"
headerText = "Database Error"
contentText = "Database problem filed to save changes"
}.showAndWait()
}
} else {
// Nothing selected.
val alert = new Alert(AlertType.Warning){
initOwner(MainApp.stage)
title = "No Selection"
headerText = "No Todo Selected"
contentText = "Please select a todo in the table."
}.showAndWait()
}
}
}
The function passed to onChange takes 3 arguments, not 2, you should have
todoTable.selectionModel().selectedItem.onChange(
(_, _, newValue) => showTodoDetails(Some(newValue))
)

Play Framework - Respond with JSON after uploading a file (multipartFormData)

I am using this code to upload an image on server , that i get from this link play upload
def upload = Action(parse.multipartFormData) { request =>
request.body
.file("picture")
.map { picture =>
val dataParts = request.body.dataParts;
val filename = Paths.get(picture.filename).getFileName
val fileSize = picture.fileSize
val contentType = picture.contentType
val picturePaths =
picture.ref.copyTo(
Paths.get(
s"/opt/docker/images/$filename"
),
replace = true
)
if (dataParts.get("firstPoint") == None) {
val pointlocation = new Point_LocationModel(
dataParts.get("step").get(0),
dataParts.get("backgroundTargetName").get(0),
dataParts.get("x").get(0),
dataParts.get("y").get(0),
dataParts.get("z").get(0),
dataParts.get("rotation").get(0),
dataParts.get("note").get(0),
dataParts.get("tag").get(0),
dataParts.get("work_session_id").get(0),
(picturePaths).toString
)
point_LocationRepository.create(pointlocation).map { data =>
Created(Json.toJson(data._2))
}
} else {
val jValuefirstPoint =
Json.parse(dataParts.get("firstPoint").get(0)).as[PointModel]
val jValuesecondPoint =
Json.parse(dataParts.get("secondPoint").get(0)).as[PointModel]
val pointlocation = new Point_LocationModel(
dataParts.get("step").get(0),
dataParts.get("backgroundTargetName").get(0),
Some(jValuefirstPoint),
Some(jValuesecondPoint),
dataParts.get("rotation").get(0),
dataParts.get("note").get(0),
dataParts.get("tag").get(0),
dataParts.get("work_session_id").get(0),
(picturePaths).toString
)
point_LocationRepository.create(pointlocation).map { data =>
logger.info(s"repoResponse: ${data}");
Created(Json.toJson(data._2))
}
}
Ok(s"picturePaths ${picturePaths}")
}
.getOrElse(Ok("Invalid Format"))
}
This code works very well, but on the response I want to get the response from the repository. How can i await for the response of the repository to return this?
Can you give me any idea how can i do it?
Thanks in advance.
If we simplify your code to the essential bits, you have:
def upload = Action(parse.multipartFormData) { request =>
request.body
.file("picture")
.map { picture =>
if (someConditionA) {
someBusinessLogicA().map { data =>
Created(Json.toJson(data._2))
}
} else {
someBusinessLogicB().map { data =>
Created(Json.toJson(data._2))
}
}
Ok(s"picturePaths ${picturePaths}")
}
.getOrElse(Ok("Invalid Format"))
}
There are 2 problems:
the return of your if/else is swallowed by the Ok(s"picturePaths ${picturePaths}")
assuming your business logic returns Future[_] you need to "propagate" the Future everywhere
Something like this should work:
def upload = Action.async(parse.multipartFormData) { request =>
request.body
.file("picture")
.map { picture =>
if (someConditionA) {
someBusinessLogicA().map { data =>
Created(Json.toJson(data._2))
}
} else {
someBusinessLogicB().map { data =>
Created(Json.toJson(data._2))
}
}
}
.getOrElse(Future.successful(Ok("Invalid Format")))
}
Notice the Action.async and the Future in the getOrElse.

Moq MongoDB UpdateOneAsync method for unit testing

I want to moq update method that is using mongodbContext. here is what i am trying to do but its not working. how to pass UpdateResult return type .ReturnsAsync<UpdateResult>(). I am very new to Mongodb database Unit Testing with .net core.
public void UpdateEventAsync_Test()
{
//Arrange
var eventRepository = EventRepository();
var pEvent = new PlanEvent
{
ID = "testEvent",
WorkOrderID = "WorkOrderID",
IsDeleted = false,
IsActive = true,
EquipmentID = "EquipmentID"
};
////Act
mockEventContext.Setup(s => s.PlanEvent.UpdateOneAsync(It.IsAny<FilterDefinition<PlanEvent>>(), It.IsAny<UpdateDefinition<Model.EventDataModel.PlanEvent>>(), It.IsAny<UpdateOptions>(), It.IsAny<System.Threading.CancellationToken>())).ReturnsAsync<UpdateResult>();
var result = eventRepository.UpdateEventAsync(pEvent);
////Assert
result.Should().NotBeNull();
Assert.AreEqual(true, result);
}
below is the code for which i want to write Moq Test
public async Task<bool> UpdateEventAsync(Model.EventDataModel.PlanEvent eventobj)
{
var filter = Builders<Model.EventDataModel.PlanEvent>.Filter.Where(f => f.ID == eventobj.ID);
// TO Do: Use replace instead of update.
var updatestatement = Builders<Model.EventDataModel.PlanEvent>.Update.Set(s => s.IsDeleted, eventobj.IsDeleted)
.Set(s => s.EquipmentID, eventobj.EquipmentID)
.Set(s => s.PlannedStartDateTime, eventobj.PlannedStartDateTime)
.Set(s => s.PlannedEndDatetime, eventobj.PlannedEndDatetime)
.Set(s => s.WorkOrderID, eventobj.WorkOrderID)
.Set(s => s.ResourceID, eventobj.ResourceID)
.Set(s => s.LastUpdatedBy, eventobj.LastUpdatedBy)
.Set(s => s.EventComment, eventobj.EventComment)
.Set(s => s.SiteID, eventobj.SiteID)
.Set(s => s.LastUpdatedDateTime, DateTime.UtcNow.ToString());
UpdateResult updateResult = await _eventContext.PlanEvent.UpdateOneAsync(filter, updatestatement);
return updateResult != null && updateResult.IsAcknowledged && updateResult.ModifiedCount > 0;
}
Either create an instance or mock UpdateResult and return that from the setup
public async Task UpdateEventAsync_Test() {
//...omitted for brevity
var mockUpdateResult = new Mock<UpdateResult>();
//Set up the mocks behavior
mockUpdateResult.Setup(_ => _.IsAcknowledged).Returns(true);
mockUpdateResult.Setup(_ => _.ModifiedCount).Returns(1);
mockEventContext
.Setup(_ => _.PlanEvent.UpdateOneAsync(It.IsAny<FilterDefinition<PlanEvent>>(), It.IsAny<UpdateDefinition<Model.EventDataModel.PlanEvent>>(), It.IsAny<UpdateOptions>(), It.IsAny<System.Threading.CancellationToken>()))
.ReturnsAsync(mockUpdateResult.Object);
//Act
var result = await eventRepository.UpdateEventAsync(pEvent);
//Assert
result.Should().Be(true);
}
Also note that the test needs to be made async to be exercised accurately.

How can I prevent some code duplication for a feed handler

I have a feed handler and I would like to prevent the data handle again if the value updated is same as previous value, so I have code like this
map.get(statisticsOpenAcronym).map { x =>
var open = x.asInstanceOf[Number].doubleValue();
if (statistics.open != open) {
statistics.open = open;
statistics.changed = true;
}
}
map.get(statisticsCloseAcronym).map { x =>
var close = x.asInstanceOf[Number].doubleValue();
if (statistics.close != close) {
statistics.close = close;
statistics.changed = true;
}
}
But then I need to have the [if xxx is difference, the update xxx and set change flag ] replicate again and again.
Just wonder, how can I prevent this?
You can compose functions (I had to change some things because I'm not sure of your types):
case class Statistic() {
var open = true
var close = !open
var changed = false
}
var statistics = Statistic()
def f(map: Map[String, String], statisticsOpenAcronym: String, statistic: Statistic, condition: Statistic => Boolean, exec: (Statistic, Boolean) => ()) = {
map.get(statisticsOpenAcronym).map { x =>
val close = x.asInstanceOf[Boolean]
if (condition(statistic)) {
exec(statistic, close)
}
}
}
def closeCondition(): Statistic => Boolean = { statistics: Statistic =>
statistics.close
}
def closeStatistic(): (Statistic, Boolean) => Unit = { (statistics: Statistic, close: Boolean) =>
statistics.close = close
statistics.changed = true;
}
f(Map.empty, "acronym", statistics, closeCondition(), closeStatistic())
Better yet you could make closeStatistics return a new statistic with the parameters you want instead of Unit.
The open case is analogue.

Entity Framework. Where clause with parameter from query as variable

Task: use different where clause in one query
Here is example (it is not real query, just to illustrate the problem)
var events = ctx.Events; // ctx - EntityFramework context
var res = events
.GroupBy(ee => ee.State)
.Select(gg => new
{
State = gg.Key,
FirstTwo = events
// how to get this clause from variable
.Where(ee => ee.State == gg.Key)
.Take(2)
})
.ToList();
Next code did not work, the problem is that where expression use parameter from query gg.Key
var events = ctx.Events;
var res = events
.GroupBy(ee => ee.State)
.Select(gg => new
{
State = gg.Key,
FirstTwo = events
// 1
// how to get this clause from variable
//.Where(ee => ee.State == gg.Key)
// 2
// try to take out where expression from query
.Where(_buildExpression(gg.Key))
.Take(2)
})
.ToList();
// method
static Expression<Func<Event, bool>> _buildExpression(string state)
{
return ee => ee.State == state;
}
// exeption
An unhandled exception of type 'System.InvalidOperationException' occurred in EntityFramework.SqlServer.dll
Additional information: variable 'gg' of type 'System.Linq.IGrouping`2[System.String,Entities.Event]' referenced from scope '', but it is not defined
Example of getting where expression from variable, but does not depend on gg.Key (wrong)
Expression<Func<Event, bool>> whereClause = (ee) => (ee.State == "test");
var events = ctx.Events;
var res = events
.GroupBy(ee => ee.State)
.Select(gg => new
{
State = gg.Key,
FirstTwo = events
// 1
// how to get this clause from variable
//.Where(ee => ee.State == gg.Key)
// 2
// try to take out where expression from query
//.Where(_buildExpression(gg.Key))
// 3
// whereClause from variable, but does not depend on gg.Key
.Where(whereClause)
.Take(2)
})
.ToList();
How to take where сlause from variable with depend on gg.Key?
p.s. the query is just example of the problem. The code below does not solve the problem of real query:
var events = ctx.Events;
var res = events
.GroupBy(ee => ee.State)
.Select(gg => new
{
State = gg.Key,
FirstTwo = gg.Take(2)
})
.ToList();
Solution by OP.
Thanks to Ivan Stoev comment.
Expression<Func<Event, string, bool>> whereClause = (ee, state) => (ee.State == state);
var events = ctx.Events;
var res = events
.AsExpandable() // <= add this
.GroupBy(ee => ee.State)
.Select(gg => new
{
State = gg.Key,
FirstTwo = events
.Where(ee => whereClause.Invoke(ee, gg.Key)) // <= Invoke expression
.Take(2)
})
.ToList();
This was made possible by LinqKit