Skip to content

Commit

Permalink
refactor: split extended.js into widget files
Browse files Browse the repository at this point in the history
  • Loading branch information
arildm committed Sep 19, 2024
1 parent 369b371 commit 02e57ff
Show file tree
Hide file tree
Showing 12 changed files with 430 additions and 388 deletions.
1 change: 0 additions & 1 deletion app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ require("./scripts/controllers/map_controller")

require("./scripts/text_reader_controller.js")
require("./scripts/video_controllers.js")
require("./scripts/extended.js")
require("./scripts/struct_services.js")
require("./scripts/filter_directives.js")
require("./scripts/matomo.js")
2 changes: 1 addition & 1 deletion app/scripts/components/extended/cqp-value.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/** @format */
import angular from "angular"
import _ from "lodash"
import extendedComponents from "@/extended.js"
import extendedComponents from "./widgets"

angular.module("korpApp").component("extendedCqpValue", {
bindings: {
Expand Down
29 changes: 29 additions & 0 deletions app/scripts/components/extended/widgets/autoc-extended.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/** @format */
import { html, regescape, unregescape } from "@/util"
import "@/components/autoc"

export const autocExtended = (options) => ({
template: html`<autoc
input="input"
is-raw-input="isRawInput"
type="${options.type || "lemgram"}"
on-change="onChange(output, isRawOutput)"
error-on-empty="${options["error_on_empty"]}"
error-message="choose_value"
></autoc>`,
controller: [
"$scope",
function ($scope) {
if ($scope.model) {
$scope.input = unregescape($scope.model)
$scope.isRawInput = false
}

$scope.onChange = (output, isRawOutput) => {
if (!isRawOutput) {
$scope.model = regescape(output)
}
}
},
],
})
91 changes: 91 additions & 0 deletions app/scripts/components/extended/widgets/common.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/** @format */
import _ from "lodash"
import settings from "@/settings"
import { locAttribute } from "@/i18n"
import { html } from "@/util"
import "@/directives/escaper"

export const selectTemplate = html`<select
ng-show="!inputOnly"
ng-model="input"
escaper
ng-options="tuple[0] as tuple[1] for tuple in dataset"
></select>
<input ng-show="inputOnly" type="text" ng-model="input" />`

export const selectController = (autocomplete) => [
"$scope",
"$rootScope",
"structService",
function ($scope, $rootScope, structService) {
$rootScope.$on("corpuschooserchange", function (event, selected) {
if (selected.length > 0) {
reloadValues()
}
})

function reloadValues() {
// TODO this exploits the API
const attributeDefinition = $scope.$parent.$ctrl.attributeDefinition
if (!attributeDefinition) {
return
}

const attribute = attributeDefinition.value
const selectedCorpora = settings.corpusListing.selected

// check which corpora support attributes
const corpora = []
for (let corpusSettings of selectedCorpora) {
if (attribute in corpusSettings["struct_attributes"] || attribute in corpusSettings.attributes) {
corpora.push(corpusSettings.id)
}
}

$scope.loading = true
const opts = { count: false, returnByCorpora: false }
if ($scope.type === "set") {
opts.split = true
}
structService.getStructValues(corpora, [attribute], opts).then(
function (data) {
$scope.loading = false

const dataset = _.map(_.uniq(data), function (item) {
if (item === "") {
return [item, loc("empty")]
}
return [item, locAttribute($scope.translation, item)]
})
$scope.dataset = _.sortBy(dataset, (tuple) => tuple[1])
if (!autocomplete) {
$scope.input = _.includes(data, $scope.input) ? $scope.input : $scope.dataset[0][0]
}
},
() => console.log("struct_values error")
)
}

// Load values initially
reloadValues()

$scope.$watch("orObj.op", (newVal, oldVal) => {
$scope.inputOnly = !["=", "!=", "contains", "not contains"].includes($scope.orObj.op)
if (newVal !== oldVal) {
if (!autocomplete) {
$scope.input = "" || $scope.dataset[0][0]
}
}
})

$scope.getRows = function (input) {
if (input) {
return _.filter($scope.dataset, (tuple) => tuple[0].toLowerCase().indexOf(input.toLowerCase()) !== -1)
} else {
return $scope.dataset
}
}

$scope.typeaheadInputFormatter = (model) => locAttribute($scope.translation, model)
},
]
42 changes: 42 additions & 0 deletions app/scripts/components/extended/widgets/dataset-select.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/** @format */
import _ from "lodash"
import { locAttribute } from "@/i18n"
import { selectTemplate } from "./common"

/**
* Select-element.
* Use the following settings in the corpus:
* - dataset: an object or an array of values
* - escape: boolean, will be used by the escaper-directive
*/
export const datasetSelect = (options) => ({
template: selectTemplate,
controller: [
"$scope",
"$rootScope",
function ($scope, $rootScope) {
let dataset
const original = $scope.dataset

$rootScope.$watch("lang", (newVal, oldVal) => {
if (newVal != oldVal) {
initialize()
}
})
function initialize() {
if (_.isArray(original)) {
dataset = _.map(original, (item) => [item, locAttribute($scope.translation, item)])
} else {
dataset = _.map(original, (v, k) => [k, locAttribute($scope.translation, v)])
}
if (options == undefined || options.sort == undefined || options.sort) {
$scope.dataset = _.sortBy(dataset, (tuple) => tuple[1])
} else {
$scope.dataset = dataset
}
$scope.model = $scope.model || $scope.dataset[0][0]
}
initialize()
},
],
})
135 changes: 135 additions & 0 deletions app/scripts/components/extended/widgets/date-interval.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/** @format */
import _ from "lodash"
import settings from "@/settings"
import moment from "moment"
import { html } from "@/util"
import "@/components/datetime-picker"

export const dateInterval = {
template: html`
<div class="date_interval_arg_type">
<h3>{{'simple' | loc:$root.lang}}</h3>
<form ng-submit="commitDateInput()">
<div class="" style="margin-bottom: 1rem;">
<span class="" style="display : inline-block; width: 32px; text-transform: capitalize;"
>{{'from' | loc:$root.lang}}</span
>
<input
type="text"
ng-blur="commitDateInput()"
ng-model="fromDateString"
placeholder="'1945' {{'or' | loc:$root.lang}} '1945-08-06'"
/>
</div>
<div>
<span class="" style="display : inline-block; width: 32px; text-transform: capitalize;"
>{{'to' | loc:$root.lang}}</span
>
<input
type="text"
ng-blur="commitDateInput()"
ng-model="toDateString"
placeholder="'1968' {{'or' | loc:$root.lang}} '1968-04-04'"
/>
</div>
<button type="submit" class="hidden"></button>
</form>
<h3>{{'advanced' | loc:$root.lang}}</h3>
<div class="section mt-4">
<datetime-picker
label="from"
date-model="fromDate"
time-model="fromTime"
min-date="minDate"
max-date="maxDate"
update="updateFrom(m)"
></datetime-picker>
</div>
<div class="section">
<datetime-picker
label="to"
date-model="toDate"
time-model="toTime"
min-date="minDate"
max-date="maxDate"
update="updateTo(m)"
></datetime-picker>
</div>
</div>
`,
controller: [
"$scope",
function ($scope) {
let s = $scope
let cl = settings.corpusListing

let updateIntervals = function () {
let moments = cl.getMomentInterval()
if (moments.length) {
let [fromYear, toYear] = _.invokeMap(moments, "toDate")
s.minDate = fromYear
s.maxDate = toYear
} else {
let [from, to] = cl.getTimeInterval()
s.minDate = moment(from.toString(), "YYYY").toDate()
s.maxDate = moment(to.toString(), "YYYY").toDate()
}
}
s.commitDateInput = () => {
if (s.fromDateString) {
const dateString = s.fromDateString.length == 4 ? `${s.fromDateString}-01-01` : s.fromDateString
s.fromDate = moment(dateString).toDate()
s.fromTime = moment("000000", "HHmmss").toDate()
}
if (s.toDateString) {
const dateString = s.toDateString.length == 4 ? `${s.toDateString}-12-31` : s.toDateString
s.toDate = moment(dateString).toDate()
s.toTime = moment("235959", "HHmmss").toDate()
}
}
s.$on("corpuschooserchange", function () {
updateIntervals()
})

updateIntervals()

let getYear = function (val) {
return moment(val.toString(), "YYYYMMDD").toDate()
}

let getTime = function (val) {
return moment(val.toString(), "HHmmss").toDate()
}

if (!s.model) {
s.fromDate = s.minDate
s.toDate = s.maxDate
let [from, to] = _.invokeMap(cl.getMomentInterval(), "toDate")
s.fromTime = from
s.toTime = to
} else if (s.model.length === 4) {
let [fromYear, toYear] = _.map(s.model.slice(0, 3), getYear)
s.fromDate = fromYear
s.toDate = toYear
let [fromTime, toTime] = _.map(s.model.slice(2), getTime)
s.fromTime = fromTime
s.toTime = toTime
}

s.updateFrom = (m) => {
// We cannot just patch the list, we need to re-set it to trigger watcher.
// [fromdate, todate, fromtime, totime]
s.model = [m.format("YYYYMMDD"), s.model[1], m.format("HHmmss"), s.model[3]]
}

s.updateTo = (m) => {
// We cannot just patch the list, we need to re-set it to trigger watcher.
// [fromdate, todate, fromtime, totime]
m.set("second", 59)
s.model = [s.model[0], m.format("YYYYMMDD"), s.model[2], m.format("HHmmss")]
}
},
],
}
53 changes: 53 additions & 0 deletions app/scripts/components/extended/widgets/default.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/** @format */
import { html } from "@/util"

export const defaultWidget = {
template: ({ placeholder }) => html`
<input
ng-model="input"
class="arg_value"
escaper
ng-model-options='{debounce : {default : 300, blur : 0}, updateOn: "default blur"}'
placeholder="${placeholder}"
/>
<span uib-dropdown>
<span
ng-class='{sensitive : case == "sensitive", insensitive : case == "insensitive"}'
class="val_mod"
uib-dropdown-toggle
>
Aa
</span>
<ul class="mod_menu" uib-dropdown-menu>
<li><a ng-click="makeSensitive()">{{'case_sensitive' | loc:$root.lang}}</a></li>
<li><a ng-click="makeInsensitive()">{{'case_insensitive' | loc:$root.lang}}</a></li>
</ul>
</span>
`,
controller: [
"$scope",
function ($scope) {
if ($scope.orObj.flags && $scope.orObj.flags.c) {
$scope.case = "insensitive"
} else {
$scope.case = "sensitive"
}

$scope.makeSensitive = function () {
$scope.case = "sensitive"
if ($scope.orObj.flags) {
delete $scope.orObj.flags["c"]
}
}

$scope.makeInsensitive = function () {
const flags = $scope.orObj.flags || {}
flags["c"] = true
$scope.orObj.flags = flags

$scope.case = "insensitive"
}
},
],
}
27 changes: 27 additions & 0 deletions app/scripts/components/extended/widgets/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/** @format */
import { autocExtended } from "./autoc-extended"
import { datasetSelect } from "./dataset-select"
import { dateInterval } from "./date-interval"
import { defaultWidget } from "./default"
import { singleValue } from "./single-value"
import { structServiceAutocomplete } from "./struct-service-autocomplete"
import { structServiceSelect } from "./struct-service-select"

const customWidgets = {}
try {
Object.assign(customWidgets, require("custom/extended.js").default)
} catch (error) {
console.log("No module for extended components available")
}

const coreWidgets = {
autocExtended,
datasetSelect,
dateInterval,
default: defaultWidget,
singleValue,
structServiceSelect,
structServiceAutocomplete,
}

export default _.merge(coreWidgets, customWidgets)
Loading

0 comments on commit 02e57ff

Please sign in to comment.