Skip to content

Commit

Permalink
refactor: Types for config/settings
Browse files Browse the repository at this point in the history
  • Loading branch information
arildm committed Jul 4, 2024
1 parent 67882b1 commit 2bb13d4
Show file tree
Hide file tree
Showing 26 changed files with 309 additions and 77 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@

## [Unreleased]

### Added

- TypeScript typings for config/settings

### Changed

- Replaced Raphael library with Chart.js, used in the pie chart over corpus distribution in statistics

### Refactoring
### Refactored

- Removed the global `c` alias for `console`
- Removed global `lang`, use `$rootScope["lang"]` instead (outside Angular: `getService("$rootScope")["lang"]`)
Expand Down
2 changes: 1 addition & 1 deletion app/scripts/backend/base-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export default abstract class BaseProxy {
}

return _(corpus.split("|"))
.map((corpus) => parseInt(settings.corpora[corpus.toLowerCase()].info.Size))
.map((corpus) => Number(settings.corpora[corpus.toLowerCase()].info.Size))
.reduce((a, b) => a + b, 0)
})
this.total = _.reduce(tmp, (val1, val2) => val1 + val2, 0)
Expand Down
2 changes: 1 addition & 1 deletion app/scripts/backend/graph-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export class GraphProxy extends BaseProxy {
const def = $.Deferred()

const ajaxSettings: AjaxSettings = {
url: settings["korp_backend_url"] + "/count_time",
url: settings.korp_backend_url + "/count_time",
dataType: "json",
data: params,

Expand Down
6 changes: 3 additions & 3 deletions app/scripts/backend/kwic-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class KwicProxy extends BaseProxy {

function getPageInterval(): Interval {
const hpp: string | number = locationSearchGet("hpp")
const itemsPerPage = Number(hpp) || settings["hits_per_page_default"]
const itemsPerPage = Number(hpp) || settings.hits_per_page_default
const start = (page || 0) * itemsPerPage
const end = start + itemsPerPage - 1
return { start, end }
Expand All @@ -52,7 +52,7 @@ export class KwicProxy extends BaseProxy {
delete options.ajaxParams.command

const data: KorpQueryParams = {
default_context: settings["default_overview_context"],
default_context: settings.default_overview_context,
...getPageInterval(),
...options.ajaxParams,
}
Expand Down Expand Up @@ -97,7 +97,7 @@ export class KwicProxy extends BaseProxy {
this.prevRequest = data
this.prevParams = data
const ajaxSettings: AjaxSettings = {
url: settings["korp_backend_url"] + "/" + command,
url: settings.korp_backend_url + "/" + command,
data: data,
beforeSend(req, settings) {
self.prevRequest = settings
Expand Down
2 changes: 1 addition & 1 deletion app/scripts/backend/lemgram-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class LemgramProxy extends BaseProxy {
this.prevParams = params

const ajaxSettings: AjaxSettings = {
url: settings["korp_backend_url"] + "/relations",
url: settings.korp_backend_url + "/relations",
data: params,

success() {
Expand Down
4 changes: 2 additions & 2 deletions app/scripts/backend/stats-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export class StatsProxy extends BaseProxy {

const reduceValLabels = _.map(reduceVals, function (reduceVal) {
if (reduceVal === "word") {
return settings["word_label"]
return settings.word_label
}
const maybeReduceAttr = settings.corpusListing.getCurrentAttributes(settings.corpusListing.getReduceLang())[
reduceVal
Expand Down Expand Up @@ -109,7 +109,7 @@ export class StatsProxy extends BaseProxy {
this.prevParams = data
const def: JQuery.Deferred<StatisticsWorkerResult> = $.Deferred()

const url = settings["korp_backend_url"] + "/count"
const url = settings.korp_backend_url + "/count"
const ajaxSettings: AjaxSettings<KorpResponse<KorpStatsResponse>> = {
url,
data,
Expand Down
2 changes: 1 addition & 1 deletion app/scripts/backend/time-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class TimeProxy extends BaseProxy {

const dfd = $.Deferred()
const ajaxSettings: AjaxSettings = {
url: settings["korp_backend_url"] + "/timespan",
url: settings.korp_backend_url + "/timespan",
data,
}
const xhr = $.ajax(httpConfAddMethod(ajaxSettings)) as JQuery.jqXHR<KorpTimespanResponse>
Expand Down
7 changes: 3 additions & 4 deletions app/scripts/components/corpus-updates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import angular, { IScope } from "angular"
import moment from "moment"
import settings from "@/settings"
import { html } from "@/util"
import { LangMap } from "@/i18n/types"

export default angular.module("korpApp").component("corpusUpdates", {
template: html`
Expand Down Expand Up @@ -44,7 +45,7 @@ export default angular.module("korpApp").component("corpusUpdates", {
$scope.expanded = false

$ctrl.$onInit = () => {
if (settings["frontpage"]?.["corpus_updates"]) {
if (settings.frontpage?.corpus_updates) {
const limitDate = moment().subtract(6, "months")
// Find most recently updated corpora
$scope.recentUpdates = settings.corpusListing.corpora
Expand Down Expand Up @@ -74,7 +75,5 @@ type CorpusUpdatesScope = IScope & {

type Corpus = {
info: { Updated: string }
title: TranslatedString | string
title: LangMap | string
}

type TranslatedString = { [lang: string]: string }
27 changes: 12 additions & 15 deletions app/scripts/components/frontpage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,22 @@ import { isEnabled } from "@/news-service"
import "@/components/corpus-updates"
import "@/components/newsdesk"
import "@/components/search-examples"
import settings from "@/settings"

export default angular.module("korpApp").component("frontpage", {
template: html`
<div ng-if="!$ctrl.hasResult()" class="max-w-screen-md my-10 mx-auto flex gap-8 flex-wrap">
<div class="w-full flex gap-8 flex-wrap">
<section
ng-if="$ctrl.showDescription && ($root._settings['description'] || $root._settings['mode_description'])"
class="w-80 grow text-lg"
>
<div
ng-if="$root._settings['description']"
ng-bind-html="$root._settings['description'] | locObj:$root.lang | trust"
></div>
<div ng-if="$root._settings['mode_description']">
<h3 ng-if="$root._settings['mode']['label']" class="font-bold">
{{$root._settings['mode']['label'] | locObj:$root.lang}}
</h3>
<div ng-bind-html="$root._settings['mode_description'] | locObj:$root.lang | trust"></div>
<section ng-if="$ctrl.showDescription && (description || modeDescription)" class="w-80 grow text-lg">
<div ng-if="description" ng-bind-html="description | locObj:$root.lang | trust"></div>
<div ng-if="modeDescription">
<h3 ng-if="modeLabel" class="font-bold">{{modeLabel | locObj:$root.lang}}</h3>
<div ng-bind-html="modeDescription | locObj:$root.lang | trust"></div>
</div>
</section>
<search-examples ng-if="$root._settings['frontpage']['examples']" class="w-80 grow"></search-examples>
<search-examples ng-if="examples" class="w-80 grow"></search-examples>
</div>
<corpus-updates class="w-80 grow"></corpus-updates>
Expand All @@ -45,6 +38,10 @@ export default angular.module("korpApp").component("frontpage", {
$ctrl.showDescription = false

$scope.newsdeskIsEnabled = isEnabled()
$scope.description = settings.description
$scope.modeDescription = settings.mode_description
$scope.modeLabel = settings.mode?.label
$scope.examples = settings.frontpage?.examples

$ctrl.hasResult = () =>
searches.activeSearch ||
Expand Down
13 changes: 3 additions & 10 deletions app/scripts/components/search-examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import _ from "lodash"
import statemachine from "@/statemachine"
import { html } from "@/util"
import settings from "@/settings"
import { SearchExample } from "@/settings/app-settings.types"

export default angular.module("korpApp").component("searchExamples", {
template: html`
Expand Down Expand Up @@ -31,7 +32,7 @@ export default angular.module("korpApp").component("searchExamples", {

$ctrl.$onInit = () => {
// Find search query examples
const examples = settings["frontpage"]?.["examples"]
const examples = settings.frontpage?.examples
if (examples) {
// Pick three random examples
$scope.examples = _.shuffle(examples).slice(0, 3)
Expand All @@ -41,7 +42,7 @@ export default angular.module("korpApp").component("searchExamples", {
$ctrl.setSearch = (params: Record<string, any>) => {
if (params.corpus) {
const corpora = params.corpus.split(",")
$rootScope._settings.corpusListing.select(corpora)
settings.corpusListing.select(corpora)
$rootScope.$broadcast("corpuschooserchange", corpora)
}
if (params.cqp) {
Expand All @@ -56,11 +57,3 @@ export default angular.module("korpApp").component("searchExamples", {
type SearchExamplesScope = IScope & {
examples?: SearchExample[]
}

type SearchExample = {
label: TranslatedString | string
hint: TranslatedString | string
params: Record<string, string | number>
}

type TranslatedString = { [lang: string]: string }
4 changes: 2 additions & 2 deletions app/scripts/corpus_listing.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export class CorpusListing {
return this._mapping_intersection(attrs)
}

getStructAttrs() {
getStructAttrs(lang) {
return this.structAttributes
}

Expand Down Expand Up @@ -192,7 +192,7 @@ export class CorpusListing {
return true
}

stringifySelected() {
stringifySelected(onlyMain) {
return _.map(this.selected, "id")
.map((a) => a.toUpperCase())
.join(",")
Expand Down
19 changes: 12 additions & 7 deletions app/scripts/data_init.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,14 @@ async function getConfig() {
return await response.json()
}

/**
*
* @param {import("@/settings/config.types").Config} modeSettings
* @returns {import("@/settings/config.types").ConfigTransformed}
*/
function transformConfig(modeSettings) {
// only if the current mode is parallel, we load the special code required
if (modeSettings["parallel"]) {
if (modeSettings.parallel) {
require("./parallel/corpus_listing.js")
require("./parallel/stats_proxy.ts")
}
Expand All @@ -134,15 +139,15 @@ function transformConfig(modeSettings) {
}
}

rename(modeSettings["attributes"], "pos_attributes", "attributes")
rename(modeSettings.attributes, "pos_attributes", "attributes")

// take the backend configuration format for attributes and expand it
// TODO the internal representation should be changed to a new, more compact one.
for (const corpusId in modeSettings["corpora"]) {
const corpus = modeSettings["corpora"][corpusId]
for (const corpusId in modeSettings.corpora) {
const corpus = modeSettings.corpora[corpusId]

if (corpus["title"] == undefined) {
corpus["title"] = corpusId
if (corpus.title == undefined) {
corpus.title = corpusId
}

rename(corpus, "pos_attributes", "attributes")
Expand All @@ -151,7 +156,7 @@ function transformConfig(modeSettings) {
const attrs = {}
const newAttrList = []
for (const attrIdx in attrList) {
const attr = modeSettings["attributes"][attrType][attrList[attrIdx]]
const attr = modeSettings.attributes[attrType][attrList[attrIdx]]
attrs[attr.name] = attr
newAttrList.push(attr.name)
}
Expand Down
6 changes: 3 additions & 3 deletions app/scripts/i18n/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { LangLocMap, LangMap, LocLangMap, LocMap } from "@/i18n/types"

/** Get the current UI language. */
export function getLang(): string {
return getService("$rootScope")["lang"] || settings["default_language"]
return getService("$rootScope")["lang"] || settings.default_language
}

/**
Expand Down Expand Up @@ -37,8 +37,8 @@ export function locObj(map: LangMap | string, lang?: string): string | undefined
lang = lang || getLang()
if (map[lang]) {
return map[lang]
} else if (map[settings["default_language"]]) {
return map[settings["default_language"]]
} else if (map[settings.default_language]) {
return map[settings.default_language]
}

// fall back to the first value if neither the selected or default language are available
Expand Down
4 changes: 4 additions & 0 deletions app/scripts/i18n/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@ export type LangLocMap = LangMap<LocMap>

/** UI strings keyed first by localization key and then by language. */
export type LocLangMap = LocMap<LangMap>

export type LangString = string | LangMap

export type Labeled<T = string> = { label: LangString; value: T }
5 changes: 5 additions & 0 deletions app/scripts/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

declare module "korp_config" {
const settings: import("@/settings/settings.types").Settings
export = settings
}
15 changes: 7 additions & 8 deletions app/scripts/news-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
import Yaml from "js-yaml"
import settings from "./settings"
import moment from "moment"
import { LangString } from "./i18n/types"

export function isEnabled(): boolean {
return !!settings["news_url"]
return !!settings.news_url
}

export async function fetchNews(): Promise<NewsItem[]> {
const response = await fetch(settings["news_url"])
const response = await fetch(settings.news_url)
const feedYaml: string = await response.text()

const itemsRaw = Yaml.load(feedYaml) as NewsItemRaw[]
Expand Down Expand Up @@ -37,14 +38,12 @@ const formatDate = (date: Date) => moment(date).format("YYYY-MM-DD")
type NewsItemRaw = {
created: Date
expires?: Date
title: string | TranslatedString
body: string | TranslatedString
title: LangString
body: LangString
}

export type NewsItem = {
created: string
title: string | TranslatedString
body: string | TranslatedString
title: LangString
body: LangString
}

type TranslatedString = { [lang: string]: string }
4 changes: 3 additions & 1 deletion app/scripts/parallel/stats_proxy.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
/** @format */
import statsProxyFactory, { StatsProxy } from "@/backend/stats-proxy"
import settings from "@/settings"
import { type ParallelCorpusListing } from "./corpus_listing"

class ParallelStatsProxy extends StatsProxy {
makeParameters(reduceVals: string[], cqp: string, ignoreCase: boolean) {
let params = super.makeParameters(reduceVals, cqp, ignoreCase)
params.within = settings.corpusListing.getAttributeQuery("within").replace(/\|.*?:/g, ":")
const corpusListing = settings.corpusListing as ParallelCorpusListing
params.within = corpusListing.getAttributeQuery("within").replace(/\|.*?:/g, ":")
return params
}
}
Expand Down
14 changes: 14 additions & 0 deletions app/scripts/settings/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Settings and config

**Config** refers to a body of configuration that mainly describes the corpus data, including the _modes_ that are used to organize them, and the _attributes_ which are found in the data.
The config is mainly fetched from the backend, which does little more than read it from a bunch of YAML files.
Once fetched, they are transformed from its current structure to a previous version of the structure – only because we haven't put time into updating the usage in code yet.
(This should probably be remedied after introduction of more TypeScript.)

**Settings** is configuration for the frontend app. It is read from the configuration directory (confusingly, as `config.yml`; see [frontend_devel.md](../../doc/frontend_devel.md)).

However, the transformed config and the settings are then merged into the same object.
This object is then used with `import settings from "@/settings"`.

As an exception to the serializable structure of `settings`, the **corpus listing** singleton object (`CorpusListing` or `ParallelCorpusListing`) lives as `settings.corpusListing`.
This is weird and should probably change.
Loading

0 comments on commit 2bb13d4

Please sign in to comment.