Skip to content

Commit

Permalink
refactor: simplify Searches service
Browse files Browse the repository at this point in the history
- Trigger search directly, not relying on $location update
- Move getCqpExpr() to $rootScope.getActiveCqp()
- Await init defs only for initial search
  • Loading branch information
arildm committed Mar 3, 2025
1 parent 291aab8 commit 3b29ad3
Show file tree
Hide file tree
Showing 12 changed files with 130 additions and 133 deletions.
17 changes: 11 additions & 6 deletions app/scripts/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
IComponentOptions,
ILocaleService,
ILocationProvider,
IQService,
IScope,
ITimeoutService,
ui,
Expand All @@ -18,7 +17,7 @@ import * as authenticationProxy from "@/components/auth/auth"
import { initLocales } from "@/data_init"
import { RootScope } from "@/root-scope.types"
import { CorpusTransformed } from "./settings/config-transformed.types"
import { getService, html } from "@/util"
import { deferOk, getService, html } from "@/util"
import { loc, locObj } from "@/i18n"
import "@/components/app-header"
import "@/components/searchtabs"
Expand Down Expand Up @@ -121,7 +120,6 @@ korpApp.run([
"$locale",
"tmhDynamicLocale",
"tmhDynamicLocaleCache",
"$q",
"$timeout",
"$uibModal",
async function (
Expand All @@ -130,18 +128,25 @@ korpApp.run([
$locale: ILocaleService,
tmhDynamicLocale: tmh.tmh.IDynamicLocale,
tmhDynamicLocaleCache: ICacheObject,
$q: IQService,
$timeout: ITimeoutService,
$uibModal: ui.bootstrap.IModalService
) {
const s = $rootScope

s.extendedCQP = null
s.globalFilterData = {}
s.globalFilterDef = $q.defer<never>()
s.langDef = $q.defer<never>()
$rootScope.globalFilterDef = deferOk()
$rootScope.langDef = deferOk()
$rootScope.wordpicSortProp = "freq"

/** Get CQP corresponding to the current search, if any. */
$rootScope.getActiveCqp = () => {
if (!$rootScope.activeSearch) return undefined
// Simple search puts CQP in `simpleCQP`. Extended/advanced puts it in `activeSearch.val`.
const isSimple = ["word", "lemgram"].includes($rootScope.activeSearch.type)
return isSimple ? $rootScope.simpleCQP : $rootScope.activeSearch.val
}

// Listen to url changes like #?lang=swe
s.$on("$locationChangeSuccess", () => {
// Update current locale. This is async and triggers the "$localeChangeSuccess" event.
Expand Down
13 changes: 7 additions & 6 deletions app/scripts/components/advanced-search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "@/services/compare-searches"
import "@/components/search-submit"
import { LocationService } from "@/urlparams"
import { CompareSearches } from "@/services/compare-searches"
import { SearchesService } from "@/services/searches"

type AdvancedSearchController = IController & {
cqp: string
Expand Down Expand Up @@ -62,15 +63,15 @@ angular.module("korpApp").component("advancedSearch", {
</div>`,
bindings: {},
controller: [
"compareSearches",
"$location",
"$scope",
"$timeout",
"compareSearches",
"searches",
function (
compareSearches: CompareSearches,
$location: LocationService,
$scope: AdvancedSearchScope,
$timeout: ITimeoutService
compareSearches: CompareSearches,
searches: SearchesService
) {
const $ctrl = this as AdvancedSearchController

Expand All @@ -92,12 +93,12 @@ angular.module("korpApp").component("advancedSearch", {
)

$ctrl.onSearch = () => {
$location.search("search", null)
$location.search("page", null)
$location.search("within", null)
$location.search("in_order", $ctrl.freeOrder ? false : null)
$timeout(() => $location.search("search", `cqp|${$ctrl.cqp}`), 0)
$location.search("search", `cqp|${$ctrl.cqp}`)
matomoSend("trackEvent", "Search", "Submit search", "Advanced")
searches.doSearch()
}

$ctrl.onSearchSave = (name) => {
Expand Down
31 changes: 12 additions & 19 deletions app/scripts/components/extended/extended-parallel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import "@/components/extended/tokens"
import { ParallelCorpusListing } from "@/parallel/corpus_listing"
import { LocationService } from "@/urlparams"
import { RootScope } from "@/root-scope.types"
import { SearchesService } from "@/services/searches"

type ExtendedParallelController = IController & {
langs: { lang: string; cqp: string }[]
negates: boolean[]
initialized: boolean
cqpChange: (idx: number) => (cqp: string) => void
negChange: () => void
onLangChange: () => void
getEnabledLangs: (i?: number) => string[]
addLangRow: () => void
Expand All @@ -39,13 +39,7 @@ angular.module("korpApp").component("extendedParallel", {
for="negate_chk{{$index}}"
>{{"not_containing" | loc:$root.lang}}</label
>
<input
type="checkbox"
id="negate_chk{{$index}}"
ng-show="!$first"
ng-model="$ctrl.negates[$index]"
ng-change="$ctrl.negChange()"
/>
<input type="checkbox" id="negate_chk{{$index}}" ng-show="!$first" ng-model="$ctrl.negates[$index]" />
<extended-tokens
cqp="l.cqp"
cqp-change="$ctrl.cqpChange($index)(cqp)"
Expand Down Expand Up @@ -78,7 +72,13 @@ angular.module("korpApp").component("extendedParallel", {
"$location",
"$rootScope",
"$timeout",
function ($location: LocationService, $rootScope: RootScope, $timeout: ITimeoutService) {
"searches",
function (
$location: LocationService,
$rootScope: RootScope,
$timeout: ITimeoutService,
searches: SearchesService
) {
const ctrl = this as ExtendedParallelController

const corpusListing = settings.corpusListing as ParallelCorpusListing
Expand Down Expand Up @@ -111,10 +111,6 @@ angular.module("korpApp").component("extendedParallel", {
}
}

ctrl.negChange = function () {
$location.search("search", null)
}

const onCQPChange = () => {
const currentLangList = _.map(ctrl.langs, "lang")
var struct = corpusListing.getLinksFromLangs(currentLangList)
Expand Down Expand Up @@ -163,14 +159,11 @@ angular.module("korpApp").component("extendedParallel", {
}

ctrl.onSubmit = function () {
// Unset and set query in next time step in order to trigger changes correctly in `searches`.
$location.search("search", null)
$location.replace()
$timeout(function () {
$location.search("search", `cqp|${onCQPChange()}`)
$location.search("page", null)
}, 0)
$location.search("search", `cqp|${onCQPChange()}`)
$location.search("page", null)
matomoSend("trackEvent", "Search", "Submit search", "Extended")
searches.doSearch()
}

ctrl.keydown = function ($event: KeyboardEvent) {
Expand Down
14 changes: 7 additions & 7 deletions app/scripts/components/extended/extended-standard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import "@/global-filter/global-filters"
import { LocationService } from "@/urlparams"
import { RootScope } from "@/root-scope.types"
import { CompareSearches } from "@/services/compare-searches"
import { SearchesService } from "@/services/searches"

type ExtendedStandardController = IController & {
cqp: string
Expand Down Expand Up @@ -72,14 +73,16 @@ angular.module("korpApp").component("extendedStandard", {
"$location",
"$rootScope",
"$scope",
"compareSearches",
"$timeout",
"compareSearches",
"searches",
function (
$location: LocationService,
$rootScope: RootScope,
$scope: ExtendedStandardScope,
$timeout: ITimeoutService,
compareSearches: CompareSearches,
$timeout: ITimeoutService
searches: SearchesService
) {
const ctrl = this as ExtendedStandardController

Expand All @@ -91,14 +94,11 @@ angular.module("korpApp").component("extendedStandard", {

// TODO this is *too* weird
function triggerSearch() {
// Unset and set query in next time step in order to trigger changes correctly in `searches`.
$location.search("search", null)
$location.search("page", null)
$location.search("in_order", $scope.freeOrder ? false : null)
$location.search("within", ctrl.within != defaultWithin ? ctrl.within : undefined)
$timeout(function () {
$location.search("search", "cqp")
}, 0)
$location.search("search", "cqp")
searches.doSearch()
}

statemachine.listen("cqp_search", (event) => {
Expand Down
5 changes: 4 additions & 1 deletion app/scripts/components/search-examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import settings from "@/settings"
import { SearchExample } from "@/settings/app-settings.types"
import { HashParams, LocationService } from "@/urlparams"
import { CqpSearchEvent } from "@/statemachine/types"
import { SearchesService } from "@/services/searches"

export default angular.module("korpApp").component("searchExamples", {
template: html`
Expand All @@ -26,7 +27,8 @@ export default angular.module("korpApp").component("searchExamples", {
controller: [
"$scope",
"$location",
function ($scope: SearchExamplesScope, $location: LocationService) {
"searches",
function ($scope: SearchExamplesScope, $location: LocationService, searches: SearchesService) {
const $ctrl = this

$scope.examples = undefined
Expand All @@ -46,6 +48,7 @@ export default angular.module("korpApp").component("searchExamples", {
}
// Do not use `$location.search(params)` because it will remove existing params (like `corpus`)
Object.keys(params).forEach((key: keyof HashParams) => $location.search(key, params[key]))
searches.doSearch()
}
},
],
Expand Down
4 changes: 2 additions & 2 deletions app/scripts/components/search-history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ angular.module("korpApp").component("searchHistory", {
const params = $scope.value.params
getSearchParamNames().forEach((key) => $location.search(key, params[key] ?? null))

// The Searches watcher stupidly only watches the `search` param, so trigger it explicitly
searches.triggerSearch()
// Wait for param changes like corpus selection to propagate to app state
$scope.$applyAsync(() => searches.doSearch())
} else if ($scope.value.id == "_clear") {
searchHistory.clear()
resetValue()
Expand Down
38 changes: 18 additions & 20 deletions app/scripts/components/simple-search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,27 +152,32 @@ angular.module("korpApp").component("simpleSearch", {
$location.search("isCaseInsensitive", "")
}

// triggers watch on activeSearch, via the Searches service
// React to changes in URL params
function readSearchParams() {
const search = $location.search()
ctrl.freeOrder = search.in_order != null
ctrl.prefix = search.prefix != null
ctrl.mid_comp = search.mid_comp != null
ctrl.suffix = search.suffix != null
ctrl.isCaseInsensitive = search.isCaseInsensitive != null
}
readSearchParams()

ctrl.updateSearch = function () {
$location.search("in_order", ctrl.freeOrder && ctrl.freeOrderEnabled ? false : null)
$location.search("prefix", ctrl.prefix ? true : null)
$location.search("mid_comp", ctrl.mid_comp ? true : null)
$location.search("suffix", ctrl.suffix ? true : null)
$location.search("isCaseInsensitive", ctrl.isCaseInsensitive ? true : null)
$location.search("within", null)

// Unset and set query in next time step in order to trigger changes correctly in the Searches service.
$location.search("search", null)
$location.replace()
$timeout(function () {
if (ctrl.currentText) {
$location.search("search", `word|${ctrl.currentText}`)
} else if (ctrl.lemgram) {
$location.search("search", `lemgram|${ctrl.lemgram}`)
}
$location.search("page", null)
}, 0)

if (ctrl.currentText) $location.search("search", `word|${ctrl.currentText}`)
else if (ctrl.lemgram) $location.search("search", `lemgram|${ctrl.lemgram}`)
$location.search("page", null)

matomoSend("trackEvent", "Search", "Submit search", "Simple")
searches.doSearch()
}

ctrl.getCQP = function () {
Expand Down Expand Up @@ -286,14 +291,7 @@ angular.module("korpApp").component("simpleSearch", {
})

// React to changes in URL params
$scope.$on("$locationChangeSuccess", () => {
const search = $location.search()
ctrl.freeOrder = search.in_order != null
ctrl.prefix = search.prefix != null
ctrl.mid_comp = search.mid_comp != null
ctrl.suffix = search.suffix != null
ctrl.isCaseInsensitive = search.isCaseInsensitive != null
})
$scope.$on("$locationChangeSuccess", () => readSearchParams())

ctrl.onChange = (value, isPlain) => {
ctrl.currentText = isPlain ? value : undefined
Expand Down
2 changes: 1 addition & 1 deletion app/scripts/components/statistics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ angular.module("korpApp").component("statistics", {
$ctrl.noRowsError = false

// TODO this is wrong, it should use the previous search
let cqp = searches.getCqpExpr()
let cqp = $rootScope.getActiveCqp()!
try {
cqp = expandOperators(cqp)
} catch {}
Expand Down
8 changes: 5 additions & 3 deletions app/scripts/controllers/statistics_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,11 @@ angular.module("korpApp").directive("statsResultCtrl", () => ({
} else {
$location.search("show_stats", true)
}
const cqp = searches.getCqpExpr()
s.showStatistics = true
s.makeRequest(cqp)
const cqp = $rootScope.getActiveCqp()
if (cqp) {
s.showStatistics = true
s.makeRequest(cqp)
}
}
},
],
Expand Down
6 changes: 4 additions & 2 deletions app/scripts/root-scope.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { CorpusListing } from "./corpus_listing"
import { CompareResult, MapRequestResult } from "@/backend/backend"
import { RelationsParams } from "@/backend/types/relations"
import { Attribute } from "./settings/config.types"
import { DeferredOk } from "./util"

/** Extends the Angular Root Scope interface with properties used by this app. */
export type RootScope = IRootScopeService & {
Expand All @@ -16,13 +17,14 @@ export type RootScope = IRootScopeService & {
val: string
} | null
extendedCQP: string | null
getActiveCqp(): string | undefined
/** Filter data by attribute name */
globalFilterData: Record<string, FilterData>
globalFilter: CqpQuery | null
/** This deferred is used to signal that the filter feature is ready. */
globalFilterDef: IDeferred<never>
globalFilterDef: DeferredOk
/** This deferred is resolved when parallel search controller is loaded */
langDef: IDeferred<never>
langDef: DeferredOk
simpleCQP?: string
show_modal: "about" | false
compareTabs: CompareTab[]
Expand Down
Loading

0 comments on commit 3b29ad3

Please sign in to comment.