Firebase firestore document changes - firebase

I just want to ask how can I properly use the document changes in my app? Btw there are 3 types of that which is ADDED, MODIFIED and lastly REMOVED. TYPE.ADDED works perfectly fine, but in modified and removed it doesn't work well in modified it. I am using a recyclerview for that and here's my code. Am I wrong utilizing it? Also, I am using a instance oldindex and newindex to know the index which is affected by the action performed.
for (DocumentChange doc : documentSnapshots.getDocumentChanges()) {
if(doc.getType() == DocumentChange.Type.ADDED) {
PostsClass post = doc.getDocument().toObject(PostsClass.class).withId(doc.getDocument().getId());
postList.add(post);
Log.d(TAG, post.toString());
postsAdapter.notifyDataSetChanged();
}
else if (doc.getType() == DocumentChange.Type.MODIFIED) {
adoptList.clear();
AdoptClass adopt = doc.getDocument().toObject(AdoptClass.class).withId(doc.getDocument().getId());
adoptList.add(adopt);
adoptListAdapter.notifyItemChanged(oldIndex);
}
else if (doc.getType() == DocumentChange.Type.REMOVED) {
adoptList.remove(oldIndex);
adoptListAdapter.notifyItemRemoved(oldIndex);
}
}

below code worked for me in 3 conditions ADDED,MODIFIED,REMOVED (Android Firestore)
for (DocumentChange documentChange : queryDocumentSnapshots.getDocumentChanges()) {
if (documentChange.getType() == DocumentChange.Type.ADDED) {
String doc_id = documentChange.getDocument().getId();
PostModel postModel = documentChange.getDocument().toObject(PostModel.class).withDocId(doc_id);
postModelList.add(postModel);
} else if (documentChange.getType() == DocumentChange.Type.MODIFIED) {
// modifying
String docID = documentChange.getDocument().getId();
PostModel changedModel = documentChange.getDocument().toObject(PostModel.class).withDocId(docID);
if (documentChange.getOldIndex() == documentChange.getNewIndex()) {
// Item changed but remained in same position
postModelList.set(documentChange.getOldIndex(),changedModel);
postListAdapter.notifyItemChanged(documentChange.getOldIndex());
}else {
// Item changed and changed position
postModelList.remove(documentChange.getOldIndex());
postModelList.add(documentChange.getNewIndex(),changedModel);
postListAdapter.notifyItemMoved(documentChange.getOldIndex(),documentChange.getNewIndex());
}
postListAdapter.notifyDataSetChanged();
} else if (documentChange.getType() == DocumentChange.Type.REMOVED) {
// remove
postModelList.remove(documentChange.getOldIndex());
postListAdapter.notifyItemRemoved(documentChange.getOldIndex());
}
}

Related

Hiding fields in Quick View form with JS not working

I need to hide few fields in a Quick View Form based on an Option Set (Choice) selection in that Quick View form. However it is not working, so am sharing the code I used for the same here. In my code, I am trying to hide certain fields if the option selected is not equal to a particular value...
function hideFields(executionContext) {
var formContext = executionContext.getFormContext();
var quickViewControl = formContext.ui.quickForms.get("General");
if (quickViewControl != undefined) {
if (quickViewControl.isLoaded()) {
var orgtypevalue = quickViewControl.getControl("new_organizationtype").getValue();
if (orgtypevalue != 248870006) {
quickViewControl.getControl("new_recipienttype").setVisible(false);
quickViewControl.getControl("new_businesstype").setVisible(false);
quickViewControl.getControl("new_businesstypecode").setVisible(false);
quickViewControl.getControl("new_businesstypecharacteristicstypecode").setVisible(false);
return;
}
else {
// Wait for some time and check again
setTimeout(getAttributeValue, 10, executionContext);
}
}
else {
console.log("No data to display in the quick view control.");
return;
}
else {
quickViewControl.getControl("new_recipienttype").setVisible(true);
quickViewControl.getControl("new_businesstype").setVisible(true);
quickViewControl.getControl("new_businesstypecode").setVisible(true);
quickViewControl.getControl("new_businesstypecharacteristicstypecode").setVisible(true);
return;
}
}
}
I need to know where am I wrong. Any help will be appreciated.
Thanks!
you need to update the following
first if version 9 I am updating this
"var quickViewControl = formContext.ui.quickForms.get("General");"
to "var quickViewControl = formContext._ui._quickForms.get("General");"
&
"var orgtypevalue = quickViewControl.getControl("new_organizationtype").getValue();"
to
"var orgtypevalue = quickViewControl.getAttribute("new_organizationtype").getValue();"
& update else with message to wait and call the function again like this
"setTimeout(hideFields, 10, executionContext);"
and add else for the If of "quickViewControl != undefined"
Kindly find the updated code:
function hideFields(executionContext) {
var formContext = executionContext.getFormContext();
var quickViewControl = formContext._ui._quickForms.get("General");
if (quickViewControl != undefined) {
if (quickViewControl.isLoaded()) {
var orgtypevalue = quickViewControl.getAttribute("new_organizationtype").getValue();
if (orgtypevalue != 248870006) {
quickViewControl.getControl("new_recipienttype").setVisible(false);
quickViewControl.getControl("new_businesstype").setVisible(false);
quickViewControl.getControl("new_businesstypecode").setVisible(false);
quickViewControl.getControl("new_businesstypecharacteristicstypecode").setVisible(false);
return;
}
else {
// Wait for some time and check again
setTimeout(hideFields, 10, executionContext);
}
}
else {
//console.log("No data to display in the quick view control.");
//return;
setTimeout(hideFields, 10, executionContext);
}
}
}

TornadoFX:proper way to bind model

I was taking a look at this :
tornadofx
and tried to expand on it with database connection and little more options, (not all of them make sense, but its just playing in a sandbox).
Even though table can be directly edited and the data will persist in database, i did try to do edit through text fields too. actual table editing would happen through different view and not table itself, as i said its just example.
Database used is Jetbrains Exposed.
object Categories : IntIdTable() {
val name = varchar("name", 64).uniqueIndex()
val description = varchar("description", 128)
}
class Category(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<Category>(Categories)
var name by Categories.name
var description by Categories.description
override fun toString(): String {
return "Category(name=\"$name\", description=\"$description\")"
}
}
now controller looks something like this, functions are just rudimentary and picked as an example.
typealias ModelToDirtyState = Map.Entry<CategoryModel, TableColumnDirtyState<CategoryModel>>
class CategoryModel() : ItemViewModel<Category>() {
val name: SimpleStringProperty = bind(Category::name)
val description: SimpleStringProperty = bind(Category::description)
}
class DBController : Controller() {
val categories: ObservableList<CategoryModel> by lazy {
transaction {
SchemaUtils.create(Categories)
Category.all().map {
CategoryModel().apply {
item = it
}
}.observable()
}
}
init {
Database.connect(
"jdbc:mysql://localhost:3306/test", driver = "com.mysql.cj.jdbc.Driver",
user = "test", password = "test"
)
TransactionManager.manager.defaultIsolationLevel = Connection.TRANSACTION_SERIALIZABLE
}
fun deleteCategory(model: CategoryModel) {
runAsync {
transaction {
model.item.delete()
}
}
categories.remove(model)
}
fun updateCategory(model: CategoryModel) {
transaction {
Categories.update {
model.commit()
}
}
}
fun commitDirty(modelDirtyMappings: Sequence<ModelToDirtyState>) {
transaction {
modelDirtyMappings.filter { it.value.isDirty }.forEach {
it.key.commit()
println(it.key)// commit value to database
it.value.commit() // clear dirty state
}
}
}
Just to quickly comment on controller, delete method works as "intended" however the update one does not, it does not work in sense that after using delete item is remove both from database and tableview(underlying list) itself, and when i do update its not, now i know the reason, i call remove manually on both database and list, now for update perhaps i could do change listener, or maybe tornadofx can do this for me, i just cant set it up to do it. Following code will make things clearer i think.
class CategoryEditor : View("Categories") {
val categoryModel: CategoryModel by inject()
val dbController: DBController by inject()
var categoryTable: TableViewEditModel<CategoryModel> by singleAssign()
var categories: ObservableList<CategoryModel> by singleAssign()
override val root = borderpane {
categories = dbController.categories
center = vbox {
buttonbar {
button("Commit") {
action {
dbController.commitDirty(categoryTable.items.asSequence())
}
}
button("Roll;back") {
action {
categoryTable.rollback()
}
}
// This model only works when i use categorytable.tableview.selected item, if i use categoryModel, list gets updated but not the view itself
// Question #1 how to use just categoryModel variable without need to use categorytable.tableview.selecteditem
button("Delete ") {
action {
val model = categoryTable.tableView.selectedItem
when (model) {
null -> return#action
else -> dbController.deleteCategory(model)
}
}
}
//And here no matter what i did i could not make the view update
button("Update") {
action {
when (categoryModel) {
null -> return#action
else -> dbController.updateCategory(categoryModel)
}
categoryTable.tableView.refresh()
}
}
}
tableview<CategoryModel> {
categoryTable = editModel
items = categories
enableCellEditing()
enableDirtyTracking()
onUserSelect() {
//open a dialog
}
//DOES WORK
categoryModel.rebindOnChange(this) { selectedItem ->
item = selectedItem?.item ?: CategoryModel().item
}
// Question #2. why bindSelected does not work, and i have to do it like above
//DOES NOT WORK
// bindSelected(categoryModel)
//
column("Name", CategoryModel::name).makeEditable()
column("Description", CategoryModel::description).makeEditable()
}
}
right = form {
fieldset {
field("Name") {
textfield(categoryModel.name)
}
}
fieldset {
field("Description") {
textfield(categoryModel.description)
}
}
button("ADD CATEGORY") {
action {
dbController.addCategory(categoryModel.name.value, categoryModel.description.value)
}
}
}
}
}
I apologize for huge amount of code, also in last code snipped i left questions in form of comments where i fail to achive desired results.
I am sure i am not properly binding code, i just dont see why, also i sometimes use one variable to update data, my declared one "categoryModel" and sometimes i use tableview.selecteditem, it just seems hacky and i cant seem to grasp way.
Thank you!

Using MvcSiteMap how do I create links to next and previous nodes?

I'd like to implement something like the following HTML helpers in MvcSiteMapProvider:
Html.MvcSiteMap().Previous()
Html.MvcSiteMap().Next()
However, I am quite new to their API, is it possible to do that, and if so, how?
You can accomplish this by building custom HTML helpers. I have answered this question already at GitHub and provided a working demo project, but I am copying here for reference.
The logic to walk up and down the document would look something like this, the rest of the code is for the most part boilerplate templated HTML helper code.
private static ISiteMapNode GetNextNode(ISiteMapNode startingNode, IDictionary<string, object> sourceMetadata)
{
ISiteMapNode nextNode = null;
if (startingNode.HasChildNodes)
{
// Get the first child node
nextNode = startingNode.ChildNodes[0];
}
else if (startingNode.ParentNode != null)
{
// Get the next sibling node
nextNode = startingNode.NextSibling;
if (nextNode == null)
{
// If there are no more siblings, the next position
// should be the parent's next sibling
var parent = startingNode.ParentNode;
if (parent != null)
{
nextNode = parent.NextSibling;
}
}
}
// If the node is not visible or accessible, run the operation recursively until a visible node is found
if (nextNode != null && !(nextNode.IsVisible(sourceMetadata) || nextNode.IsAccessibleToUser()))
{
nextNode = GetNextNode(nextNode, sourceMetadata);
}
return nextNode;
}
private static ISiteMapNode GetPreviousNode(ISiteMapNode startingNode, IDictionary<string, object> sourceMetadata)
{
ISiteMapNode previousNode = null;
// Get the previous sibling
var previousSibling = startingNode.PreviousSibling;
if (previousSibling != null)
{
// If there are any children, go to the last descendant
if (previousSibling.HasChildNodes)
{
previousNode = previousSibling.Descendants.Last();
}
else
{
// If there are no children, return the sibling.
previousNode = previousSibling;
}
}
else
{
// If there are no more siblings before this one, go to the parent node
previousNode = startingNode.ParentNode;
}
// If the node is not visible or accessible, run the operation recursively until a visible node is found
if (previousNode != null && !(previousNode.IsVisible(sourceMetadata) || previousNode.IsAccessibleToUser()))
{
previousNode = GetPreviousNode(previousNode, sourceMetadata);
}
return previousNode;
}

How to make sure a value isn't already in a Meteor collection?

Something like:
if (myCollection.find({'thingamaJig.$' : 'number1'}) = null) {
"number1 is NOT in myCollection" }
else { "number1 is already in myCollection!" }
?
You can use findOne
if(!myCollection.findOne({thingamagig:number1})) {
//Number1 not in collection
}
This will work even if thingamagic is an array e.g
a document looks like:
{thingamagig : [1,4,5,9]}
This would run because 10 isn't in the array
if(myCollection.findOne({thingamagig:10}) == null) {
//Not in collection
}

Using webdriver, I am able to run successfully for the first user & for next user it is failing at if condition. If condition is not working properly

If condition is not working properly. I have some set of user id to login to my application, using webdriver, I am able to run successfully for the first user & for next user it is failing at if condition. Please find the code below and it has to check the more if conditions to run successfully.
for (int i = 1; i < sh.getRows(); i++)
{
while(iter.hasNext())
{
System.out.println("Main Window ID :"+iter.next());
}
driver.findElement(By.id("lgnLogin_UserName")).clear();
driver.findElement(By.id("lgnLogin_UserName")).sendKeys(sh.getCell(0,
i).getContents());
driver.findElement(By.id("lgnLogin_Password")).clear();
driver.findElement(By.id("lgnLogin_Password")).sendKeys(sh.getCell(1,
i).getContents());
driver.findElement(By.id("lgnLogin_LoginButton")).click();
Thread.sleep(5000L);
if(driver.findElements(By.linkText("Logout")) != null)
{
driver.findElement(By.id("ctl00_Header_Lbtn_Logout")).click();
msg ="Valid User Login";
System.out.println(msg);
}
else
if(driver.getTitle().contains("700Dealers Inc."))
{
driver.findElement(By.xpath("//table[#id='lgnLogin']/tbody
/tr/td/table/tbody/tr[4]/td")).getText();
System.out.println(msg);
}
else
if(driver.getTitle().contains("Security Question And Answers"))
{
driver.findElement(By.xpath("//table[#id='Table_01']/tbody
/tr[5]/td/table/tbody/tr/td/table/tbody/tr/td/span/span[1]")).getText();
System.out.println(msg);
}
else
if(driver.getTitle().contains("700 credit Change Password"))
{
driver.findElement(By.xpath("//div[#id='panelscreen']/table
/tbody/tr/th/span")).getText();
System.out.println(msg);
}
Please help me out in this issue. Help will be appreciated.
Thread.sleep(5000L); is probably the root of your problems.
So, you may want to replace that :
Thread.sleep(5000L);
if(driver.findElements(By.linkText("Logout")) != null)
with an explicit wait :
try {
WebElement logout = (new WebDriverWait(driver, 5))
.until(new ExpectedCondition<WebElement>(){
#Override
public WebElement apply(WebDriver d) {
return d.findElement(By.linkText("Logout"));
}});
//Logout found, do stuff
} catch(TimeoutException e) {
//No logout element, do stuff
}

Resources