From ffb903841bb3a21c41931e84f9948c9e8c2ae41f Mon Sep 17 00:00:00 2001
From: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
Date: Mon, 13 Jun 2022 15:35:00 -0700
Subject: [PATCH] Prevent duplicate api calls on text filtering

---
 .../filter-editor/filter-editor.component.ts  | 37 +++++--------------
 src-ui/src/app/data/filter-rule.ts            | 28 ++++++++++++++
 .../services/document-list-view.service.ts    | 26 ++++++++++---
 3 files changed, 58 insertions(+), 33 deletions(-)

diff --git a/src-ui/src/app/components/document-list/filter-editor/filter-editor.component.ts b/src-ui/src/app/components/document-list/filter-editor/filter-editor.component.ts
index 421cd0693..e29b2736c 100644
--- a/src-ui/src/app/components/document-list/filter-editor/filter-editor.component.ts
+++ b/src-ui/src/app/components/document-list/filter-editor/filter-editor.component.ts
@@ -16,7 +16,7 @@ import { debounceTime, distinctUntilChanged, filter } from 'rxjs/operators'
 import { DocumentTypeService } from 'src/app/services/rest/document-type.service'
 import { TagService } from 'src/app/services/rest/tag.service'
 import { CorrespondentService } from 'src/app/services/rest/correspondent.service'
-import { FilterRule } from 'src/app/data/filter-rule'
+import { filterRulesDiffer, FilterRule } from 'src/app/data/filter-rule'
 import {
   FILTER_ADDED_AFTER,
   FILTER_ADDED_BEFORE,
@@ -204,7 +204,10 @@ export class FilterEditorComponent implements OnInit, OnDestroy {
   @Input()
   set unmodifiedFilterRules(value: FilterRule[]) {
     this._unmodifiedFilterRules = value
-    this.checkIfRulesHaveChanged()
+    this.rulesModified = filterRulesDiffer(
+      this._unmodifiedFilterRules,
+      this._filterRules
+    )
   }
 
   get unmodifiedFilterRules(): FilterRule[] {
@@ -330,7 +333,10 @@ export class FilterEditorComponent implements OnInit, OnDestroy {
           break
       }
     })
-    this.checkIfRulesHaveChanged()
+    this.rulesModified = filterRulesDiffer(
+      this._unmodifiedFilterRules,
+      this._filterRules
+    )
   }
 
   get filterRules(): FilterRule[] {
@@ -473,31 +479,6 @@ export class FilterEditorComponent implements OnInit, OnDestroy {
 
   rulesModified: boolean = false
 
-  private checkIfRulesHaveChanged() {
-    let modified = false
-    if (this._unmodifiedFilterRules.length != this._filterRules.length) {
-      modified = true
-    } else {
-      modified = this._unmodifiedFilterRules.some((rule) => {
-        return (
-          this._filterRules.find(
-            (fri) => fri.rule_type == rule.rule_type && fri.value == rule.value
-          ) == undefined
-        )
-      })
-
-      if (!modified) {
-        // only check other direction if we havent already determined is modified
-        modified = this._filterRules.some((rule) => {
-          this._unmodifiedFilterRules.find(
-            (fr) => fr.rule_type == rule.rule_type && fr.value == rule.value
-          ) == undefined
-        })
-      }
-    }
-    this.rulesModified = modified
-  }
-
   updateRules() {
     this.filterRulesChange.next(this.filterRules)
   }
diff --git a/src-ui/src/app/data/filter-rule.ts b/src-ui/src/app/data/filter-rule.ts
index 75819ad52..4460d39ab 100644
--- a/src-ui/src/app/data/filter-rule.ts
+++ b/src-ui/src/app/data/filter-rule.ts
@@ -25,6 +25,34 @@ export function isFullTextFilterRule(filterRules: FilterRule[]): boolean {
   )
 }
 
+export function filterRulesDiffer(
+  filterRulesA: FilterRule[],
+  filterRulesB: FilterRule[]
+): boolean {
+  let modified = false
+  if (filterRulesA.length != filterRulesB.length) {
+    modified = true
+  } else {
+    modified = filterRulesA.some((rule) => {
+      return (
+        filterRulesB.find(
+          (fri) => fri.rule_type == rule.rule_type && fri.value == rule.value
+        ) == undefined
+      )
+    })
+
+    if (!modified) {
+      // only check other direction if we havent already determined is modified
+      modified = filterRulesB.some((rule) => {
+        filterRulesA.find(
+          (fr) => fr.rule_type == rule.rule_type && fr.value == rule.value
+        ) == undefined
+      })
+    }
+  }
+  return modified
+}
+
 export interface FilterRule {
   rule_type: number
   value: string
diff --git a/src-ui/src/app/services/document-list-view.service.ts b/src-ui/src/app/services/document-list-view.service.ts
index b7ec2708d..a21ee1312 100644
--- a/src-ui/src/app/services/document-list-view.service.ts
+++ b/src-ui/src/app/services/document-list-view.service.ts
@@ -2,6 +2,7 @@ import { Injectable } from '@angular/core'
 import { ParamMap, Router } from '@angular/router'
 import { Observable } from 'rxjs'
 import {
+  filterRulesDiffer,
   cloneFilterRules,
   FilterRule,
   isFullTextFilterRule,
@@ -67,6 +68,7 @@ export interface ListViewState {
 })
 export class DocumentListViewService {
   isReloading: boolean = false
+  initialized: boolean = false
   error: string = null
 
   rangeSelectionAnchorIndex: number
@@ -172,11 +174,24 @@ export class DocumentListViewService {
     if (!paramsEmpty) newState = parseParams(queryParams)
     if (newState == undefined) newState = this.defaultListViewState() // if nothing in local storage
 
-    this.activeListViewState.filterRules = newState.filterRules
-    this.activeListViewState.sortField = newState.sortField
-    this.activeListViewState.sortReverse = newState.sortReverse
-    this.activeListViewState.currentPage = newState.currentPage
-    this.reload(null, paramsEmpty) // update the params if there arent any
+    // only reload if things have changed
+    if (
+      !this.initialized ||
+      paramsEmpty ||
+      this.activeListViewState.sortField !== newState.sortField ||
+      this.activeListViewState.sortReverse !== newState.sortReverse ||
+      this.activeListViewState.currentPage !== newState.currentPage ||
+      filterRulesDiffer(
+        this.activeListViewState.filterRules,
+        newState.filterRules
+      )
+    ) {
+      this.activeListViewState.filterRules = newState.filterRules
+      this.activeListViewState.sortField = newState.sortField
+      this.activeListViewState.sortReverse = newState.sortReverse
+      this.activeListViewState.currentPage = newState.currentPage
+      this.reload(null, paramsEmpty) // update the params if there arent any
+    }
   }
 
   reload(onFinish?, updateQueryParams: boolean = true) {
@@ -193,6 +208,7 @@ export class DocumentListViewService {
       )
       .subscribe({
         next: (result) => {
+          this.initialized = true
           this.isReloading = false
           activeListViewState.collectionSize = result.count
           activeListViewState.documents = result.results