@fiduswriter/bibliography-manager 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +20 -0
  3. package/dist/database/index.js +172 -0
  4. package/dist/database/index.js.map +1 -0
  5. package/dist/database/server_connector.js +47 -0
  6. package/dist/database/server_connector.js.map +1 -0
  7. package/dist/export/index.js +23 -0
  8. package/dist/export/index.js.map +1 -0
  9. package/dist/form/cats.js +22 -0
  10. package/dist/form/cats.js.map +1 -0
  11. package/dist/form/fields/date.js +28 -0
  12. package/dist/form/fields/date.js.map +1 -0
  13. package/dist/form/fields/key.js +100 -0
  14. package/dist/form/fields/key.js.map +1 -0
  15. package/dist/form/fields/key_list.js +37 -0
  16. package/dist/form/fields/key_list.js.map +1 -0
  17. package/dist/form/fields/literal.js +43 -0
  18. package/dist/form/fields/literal.js.map +1 -0
  19. package/dist/form/fields/literal_list.js +36 -0
  20. package/dist/form/fields/literal_list.js.map +1 -0
  21. package/dist/form/fields/literal_long.js +42 -0
  22. package/dist/form/fields/literal_long.js.map +1 -0
  23. package/dist/form/fields/name.js +121 -0
  24. package/dist/form/fields/name.js.map +1 -0
  25. package/dist/form/fields/name_list.js +36 -0
  26. package/dist/form/fields/name_list.js.map +1 -0
  27. package/dist/form/fields/range.js +89 -0
  28. package/dist/form/fields/range.js.map +1 -0
  29. package/dist/form/fields/range_list.js +36 -0
  30. package/dist/form/fields/range_list.js.map +1 -0
  31. package/dist/form/fields/tag_list.js +30 -0
  32. package/dist/form/fields/tag_list.js.map +1 -0
  33. package/dist/form/fields/title.js +46 -0
  34. package/dist/form/fields/title.js.map +1 -0
  35. package/dist/form/fields/uri.js +40 -0
  36. package/dist/form/fields/uri.js.map +1 -0
  37. package/dist/form/fields/verbatim.js +19 -0
  38. package/dist/form/fields/verbatim.js.map +1 -0
  39. package/dist/form/index.js +344 -0
  40. package/dist/form/index.js.map +1 -0
  41. package/dist/form/strings.js +89 -0
  42. package/dist/form/strings.js.map +1 -0
  43. package/dist/form/templates.js +59 -0
  44. package/dist/form/templates.js.map +1 -0
  45. package/dist/import/bibliography_import.js +83 -0
  46. package/dist/import/bibliography_import.js.map +1 -0
  47. package/dist/import/dialog.js +71 -0
  48. package/dist/import/dialog.js.map +1 -0
  49. package/dist/import/index.js +3 -0
  50. package/dist/import/index.js.map +1 -0
  51. package/dist/import/templates.js +12 -0
  52. package/dist/import/templates.js.map +1 -0
  53. package/dist/index.js +6 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/overview/index.js +453 -0
  56. package/dist/overview/index.js.map +1 -0
  57. package/dist/overview/menu.js +91 -0
  58. package/dist/overview/menu.js.map +1 -0
  59. package/dist/overview/templates.js +24 -0
  60. package/dist/overview/templates.js.map +1 -0
  61. package/dist/plugins/bibliography_overview/index.js +2 -0
  62. package/dist/plugins/bibliography_overview/index.js.map +1 -0
  63. package/dist/schema/literal.js +24 -0
  64. package/dist/schema/literal.js.map +1 -0
  65. package/dist/schema/literal_long.js +40 -0
  66. package/dist/schema/literal_long.js.map +1 -0
  67. package/dist/schema/title.js +31 -0
  68. package/dist/schema/title.js.map +1 -0
  69. package/dist/tools.js +53 -0
  70. package/dist/tools.js.map +1 -0
  71. package/package.json +55 -0
  72. package/src/database/index.js +234 -0
  73. package/src/database/server_connector.js +57 -0
  74. package/src/export/index.js +27 -0
  75. package/src/form/cats.js +24 -0
  76. package/src/form/fields/date.js +31 -0
  77. package/src/form/fields/key.js +113 -0
  78. package/src/form/fields/key_list.js +45 -0
  79. package/src/form/fields/literal.js +48 -0
  80. package/src/form/fields/literal_list.js +42 -0
  81. package/src/form/fields/literal_long.js +47 -0
  82. package/src/form/fields/name.js +152 -0
  83. package/src/form/fields/name_list.js +42 -0
  84. package/src/form/fields/range.js +104 -0
  85. package/src/form/fields/range_list.js +42 -0
  86. package/src/form/fields/tag_list.js +33 -0
  87. package/src/form/fields/title.js +51 -0
  88. package/src/form/fields/uri.js +43 -0
  89. package/src/form/fields/verbatim.js +21 -0
  90. package/src/form/index.js +424 -0
  91. package/src/form/strings.js +122 -0
  92. package/src/form/templates.js +70 -0
  93. package/src/import/bibliography_import.js +104 -0
  94. package/src/import/dialog.js +95 -0
  95. package/src/import/index.js +2 -0
  96. package/src/import/templates.js +12 -0
  97. package/src/index.js +5 -0
  98. package/src/overview/index.js +548 -0
  99. package/src/overview/menu.js +106 -0
  100. package/src/overview/templates.js +30 -0
  101. package/src/plugins/bibliography_overview/index.js +1 -0
  102. package/src/schema/literal.js +34 -0
  103. package/src/schema/literal_long.js +50 -0
  104. package/src/schema/title.js +42 -0
  105. package/src/tools.js +58 -0
@@ -0,0 +1,27 @@
1
+ import {ZipFileCreator} from "@fiduswriter/document/exporter/tools/zip"
2
+ import download from "downloadjs"
3
+
4
+ export class BibLatexFileExporter {
5
+ constructor(bibDB, pks) {
6
+ this.pks = pks // A list of pk values of the bibliography items to be exported.
7
+ this.bibDB = bibDB // The bibliography database to export from.
8
+ }
9
+
10
+ init() {
11
+ import("bibliojson").then(({BibLatexExporter}) => {
12
+ const exporter = new BibLatexExporter(this.bibDB.db, this.pks)
13
+
14
+ const zipper = new ZipFileCreator([
15
+ {
16
+ filename: "bibliography.bib",
17
+ contents: exporter.output
18
+ }
19
+ ])
20
+ zipper
21
+ .init()
22
+ .then(blob =>
23
+ download(blob, "bibliography.zip", "application/zip")
24
+ )
25
+ })
26
+ }
27
+ }
@@ -0,0 +1,24 @@
1
+ import {CheckableList} from "fwtoolkit"
2
+
3
+ export class CatsForm {
4
+ constructor(dom, initialValue = [], options = []) {
5
+ this.dom = dom
6
+ this.checkableList = new CheckableList({
7
+ dom,
8
+ options: options.map(option => ({
9
+ id: option.id,
10
+ label: option.category_title
11
+ })),
12
+ initialValue,
13
+ multiple: true
14
+ })
15
+ }
16
+
17
+ init() {
18
+ // CheckableList is already rendered by the constructor.
19
+ }
20
+
21
+ get value() {
22
+ return this.checkableList.value
23
+ }
24
+ }
@@ -0,0 +1,31 @@
1
+ import {edtfParse} from "bibliojson"
2
+
3
+ export class DateFieldForm {
4
+ constructor(dom, initialValue = "", placeHolder = "") {
5
+ this.dom = dom
6
+ this.initialValue = initialValue
7
+ this.placeHolder = placeHolder
8
+ }
9
+
10
+ init() {
11
+ this.dom.innerHTML = `<input class="fw-date" type="text" value="${this.initialValue}" placeholder="${this.placeHolder}">`
12
+ }
13
+
14
+ get value() {
15
+ const formValue = this.dom.querySelector("input.fw-date").value
16
+ // If the form has not been filled out, don't consider this form
17
+ return formValue.length > 0 ? formValue : false
18
+ }
19
+
20
+ check() {
21
+ const formValue = this.value
22
+ if (formValue) {
23
+ const checkValue = edtfParse(formValue).valid
24
+ if (!checkValue) {
25
+ this.dom.classList.add("fw-fomt-error")
26
+ return false
27
+ }
28
+ }
29
+ return true
30
+ }
31
+ }
@@ -0,0 +1,113 @@
1
+ import {TypeSwitch} from "fwtoolkit"
2
+ import {getBibOptionTitle} from "../strings"
3
+ import {LiteralFieldForm} from "./literal"
4
+
5
+ export class KeyFieldForm {
6
+ constructor(dom, initialValue, _unused, fieldType = undefined) {
7
+ this.currentValue = {}
8
+ this.dom = dom
9
+ this.fieldType = fieldType
10
+ // We set the mode based on the type of value
11
+ if (typeof initialValue === "object") {
12
+ this.predefined = false
13
+ this.currentValue["custom"] = initialValue
14
+ } else {
15
+ this.predefined = true
16
+ this.currentValue["predefined"] = initialValue
17
+ }
18
+ }
19
+
20
+ init() {
21
+ this.typeSwitch = new TypeSwitch({
22
+ dom: this.dom,
23
+ label1: gettext("From list"),
24
+ label2: gettext("Custom"),
25
+ initialMode: this.predefined ? 1 : 2,
26
+ disabled: this.fieldType.strict,
27
+ beforeChange: () => {
28
+ const formValue = this.value
29
+ if (formValue) {
30
+ if (this.predefined) {
31
+ this.currentValue["predefined"] = formValue
32
+ } else {
33
+ this.currentValue["custom"] = formValue
34
+ }
35
+ }
36
+ },
37
+ onChange: mode => {
38
+ this.predefined = mode === 1
39
+ this.drawForm()
40
+ }
41
+ })
42
+ this.drawForm()
43
+ }
44
+
45
+ drawForm() {
46
+ if (this.predefined) {
47
+ this.drawSelectionListForm()
48
+ } else {
49
+ this.drawCustomInputForm()
50
+ }
51
+ }
52
+
53
+ drawSelectionListForm() {
54
+ this.typeSwitch.innerElement.innerHTML = `
55
+ <select class='key-selection'><option value=''></option></select>
56
+ <div class="fw-select-arrow fa fa-caret-down"></div>
57
+ `
58
+ const selectEl =
59
+ this.typeSwitch.innerElement.querySelector(".key-selection")
60
+ if (Array.isArray(this.fieldType.options)) {
61
+ this.fieldType.options.forEach(option => {
62
+ selectEl.insertAdjacentHTML(
63
+ "beforeend",
64
+ `<option value="${option}">${getBibOptionTitle(option)}</option>`
65
+ )
66
+ })
67
+ } else {
68
+ Object.keys(this.fieldType.options).forEach(option => {
69
+ selectEl.insertAdjacentHTML(
70
+ "beforeend",
71
+ `<option value="${option}">${getBibOptionTitle(option)}</option>`
72
+ )
73
+ })
74
+ }
75
+
76
+ if (this.currentValue["predefined"]) {
77
+ selectEl.value = this.currentValue["predefined"]
78
+ }
79
+ }
80
+
81
+ drawCustomInputForm() {
82
+ this.fields = {}
83
+ this.typeSwitch.innerElement.innerHTML = `<div class='custom-input field-part field-part-single'></div>`
84
+ this.fields["custom"] = new LiteralFieldForm(
85
+ this.typeSwitch.innerElement.querySelector(".custom-input"),
86
+ this.currentValue["custom"]
87
+ )
88
+ this.fields.custom.init()
89
+ }
90
+
91
+ get value() {
92
+ if (this.predefined) {
93
+ const selectEl =
94
+ this.typeSwitch.innerElement.querySelector(".key-selection")
95
+ const selectionValue =
96
+ selectEl.options[selectEl.selectedIndex].value
97
+ if (selectionValue === "") {
98
+ return false
99
+ } else {
100
+ return selectionValue
101
+ }
102
+ } else {
103
+ if (!this.fields.custom.value) {
104
+ return false
105
+ }
106
+ return this.fields.custom.value
107
+ }
108
+ }
109
+
110
+ check() {
111
+ return true
112
+ }
113
+ }
@@ -0,0 +1,45 @@
1
+ import {InputList} from "fwtoolkit"
2
+ import {KeyFieldForm} from "./key"
3
+
4
+ export class KeyListForm {
5
+ constructor(dom, initialValue = [""], _unused, fieldType = undefined) {
6
+ this.dom = dom
7
+ this.fieldType = fieldType
8
+ this.fieldHandlers = new WeakMap()
9
+ this.inputList = new InputList({
10
+ dom,
11
+ initialValues: initialValue,
12
+ emptyValue: "",
13
+ renderItem: value => ({
14
+ html: `<div class="key-field"></div>`,
15
+ bind: el => {
16
+ const fieldHandler = new KeyFieldForm(
17
+ el.firstElementChild,
18
+ value,
19
+ false,
20
+ this.fieldType
21
+ )
22
+ fieldHandler.init()
23
+ this.fieldHandlers.set(el, fieldHandler)
24
+ }
25
+ }),
26
+ getValue: el => this.fieldHandlers.get(el).value
27
+ })
28
+ }
29
+
30
+ init() {
31
+ // InputList is already rendered by the constructor.
32
+ }
33
+
34
+ get value() {
35
+ const formValue = this.inputList.values.filter(value => value !== false)
36
+ if (formValue.length === 0) {
37
+ return false
38
+ }
39
+ return formValue
40
+ }
41
+
42
+ check() {
43
+ return true
44
+ }
45
+ }
@@ -0,0 +1,48 @@
1
+ import {toggleMark} from "prosemirror-commands"
2
+
3
+ import {InlineInput, icon} from "fwtoolkit"
4
+
5
+ import {litSchema} from "../../schema/literal"
6
+
7
+ export class LiteralFieldForm {
8
+ constructor(dom, initialValue = [], placeHolder = false) {
9
+ this.inlineInput = new InlineInput(dom, {
10
+ schema: litSchema,
11
+ nodeType: "literal",
12
+ initialValue,
13
+ placeholder: placeHolder,
14
+ tools: [
15
+ {
16
+ command: toggleMark(litSchema.marks.strong),
17
+ dom: icon("strong", gettext("Strong"))
18
+ },
19
+ {
20
+ command: toggleMark(litSchema.marks.em),
21
+ dom: icon("em", gettext("Emphasis"))
22
+ },
23
+ {
24
+ command: toggleMark(litSchema.marks.smallcaps),
25
+ dom: icon("smallcaps", gettext("Small caps"))
26
+ },
27
+ {
28
+ command: toggleMark(litSchema.marks.sub),
29
+ dom: icon("sub", gettext("Subscript₊"))
30
+ },
31
+ {
32
+ command: toggleMark(litSchema.marks.sup),
33
+ dom: icon("sup", gettext("Supscript²"))
34
+ }
35
+ ]
36
+ })
37
+ }
38
+
39
+ init() {}
40
+
41
+ get value() {
42
+ return this.inlineInput.value
43
+ }
44
+
45
+ check() {
46
+ return this.inlineInput.check()
47
+ }
48
+ }
@@ -0,0 +1,42 @@
1
+ import {InputList} from "fwtoolkit"
2
+ import {LiteralFieldForm} from "./literal"
3
+
4
+ export class LiteralListForm {
5
+ constructor(dom, initialValue = [[]]) {
6
+ this.dom = dom
7
+ this.fieldHandlers = new WeakMap()
8
+ this.inputList = new InputList({
9
+ dom,
10
+ initialValues: initialValue,
11
+ emptyValue: [],
12
+ renderItem: value => ({
13
+ html: `<div class="literal-field"></div>`,
14
+ bind: el => {
15
+ const fieldHandler = new LiteralFieldForm(
16
+ el.firstElementChild,
17
+ value
18
+ )
19
+ fieldHandler.init()
20
+ this.fieldHandlers.set(el, fieldHandler)
21
+ }
22
+ }),
23
+ getValue: el => this.fieldHandlers.get(el).value
24
+ })
25
+ }
26
+
27
+ init() {
28
+ // InputList is already rendered by the constructor.
29
+ }
30
+
31
+ get value() {
32
+ const formValue = this.inputList.values.filter(value => value !== false)
33
+ if (formValue.length === 0) {
34
+ return false
35
+ }
36
+ return formValue
37
+ }
38
+
39
+ check() {
40
+ return true
41
+ }
42
+ }
@@ -0,0 +1,47 @@
1
+ import {toggleMark} from "prosemirror-commands"
2
+
3
+ import {InlineInput, icon} from "fwtoolkit"
4
+
5
+ import {longLitSchema} from "../../schema/literal_long"
6
+
7
+ export class LiteralLongFieldForm {
8
+ constructor(dom, initialValue = []) {
9
+ this.inlineInput = new InlineInput(dom, {
10
+ schema: longLitSchema,
11
+ nodeType: "longliteral",
12
+ initialValue,
13
+ tools: [
14
+ {
15
+ command: toggleMark(longLitSchema.marks.strong),
16
+ dom: icon("strong", gettext("Strong"))
17
+ },
18
+ {
19
+ command: toggleMark(longLitSchema.marks.em),
20
+ dom: icon("em", gettext("Emphasis"))
21
+ },
22
+ {
23
+ command: toggleMark(longLitSchema.marks.smallcaps),
24
+ dom: icon("smallcaps", gettext("Small caps"))
25
+ },
26
+ {
27
+ command: toggleMark(longLitSchema.marks.sub),
28
+ dom: icon("sub", gettext("Subscript₊"))
29
+ },
30
+ {
31
+ command: toggleMark(longLitSchema.marks.sup),
32
+ dom: icon("sup", gettext("Supscript²"))
33
+ }
34
+ ]
35
+ })
36
+ }
37
+
38
+ init() {}
39
+
40
+ get value() {
41
+ return this.inlineInput.value
42
+ }
43
+
44
+ check() {
45
+ return this.inlineInput.check()
46
+ }
47
+ }
@@ -0,0 +1,152 @@
1
+ import {TypeSwitch, getFocusIndex, setFocusIndex} from "fwtoolkit"
2
+ import {LiteralFieldForm} from "./literal"
3
+
4
+ // There are only name lists, no name fields in the data format. The separation
5
+ // between NameFieldForm and NameListForm is for keeping consistency with other fields
6
+ // and lists.
7
+
8
+ export class NameFieldForm {
9
+ constructor(
10
+ dom,
11
+ initialValue = {
12
+ given: [],
13
+ family: [],
14
+ prefix: [],
15
+ suffix: [],
16
+ useprefix: false,
17
+ literal: []
18
+ }
19
+ ) {
20
+ this.currentValue = initialValue
21
+ this.dom = dom
22
+ // We set the mode based on whether there was a literal name.
23
+ if (initialValue.literal) {
24
+ this.realPerson = false
25
+ } else {
26
+ this.realPerson = true
27
+ }
28
+ }
29
+
30
+ init() {
31
+ this.typeSwitch = new TypeSwitch({
32
+ dom: this.dom,
33
+ label1: gettext("Person"),
34
+ label2: gettext("Organization"),
35
+ initialMode: this.realPerson ? 1 : 2,
36
+ beforeChange: () => {
37
+ const formValue = this.value
38
+ if (formValue) {
39
+ Object.assign(this.currentValue, formValue)
40
+ }
41
+ },
42
+ onChange: mode => {
43
+ this.realPerson = mode === 1
44
+ const focusIndex = getFocusIndex()
45
+ this.drawForm()
46
+ setFocusIndex(focusIndex)
47
+ }
48
+ })
49
+ this.drawForm()
50
+ }
51
+
52
+ drawForm() {
53
+ if (this.realPerson) {
54
+ this.drawPersonForm()
55
+ } else {
56
+ this.drawOrganizationForm()
57
+ }
58
+ }
59
+
60
+ drawPersonForm() {
61
+ this.fields = {}
62
+ this.typeSwitch.innerElement.innerHTML = `
63
+ <div class='given field-part field-part-long'></div>
64
+ <div class='prefix field-part field-part-short'></div>
65
+ <div class='family field-part field-part-long'></div>
66
+ <div class='suffix field-part field-part-short'></div>
67
+ <div class='useprefix field-part'>
68
+ <input type='checkbox' class='useprefix'
69
+ ${this.currentValue.useprefix ? "checked" : ""}>
70
+ &nbsp;${gettext("Prefix used")}
71
+ </div>
72
+ `
73
+ this.fields["given"] = new LiteralFieldForm(
74
+ this.typeSwitch.innerElement.querySelector(".given"),
75
+ this.currentValue.given,
76
+ gettext("First name")
77
+ )
78
+ this.fields.given.init()
79
+ this.fields["prefix"] = new LiteralFieldForm(
80
+ this.typeSwitch.innerElement.querySelector(".prefix"),
81
+ this.currentValue.prefix,
82
+ gettext("Prefix")
83
+ )
84
+ this.fields.prefix.init()
85
+ this.fields["family"] = new LiteralFieldForm(
86
+ this.typeSwitch.innerElement.querySelector(".family"),
87
+ this.currentValue.family,
88
+ gettext("Last name")
89
+ )
90
+ this.fields.family.init()
91
+ this.fields["suffix"] = new LiteralFieldForm(
92
+ this.typeSwitch.innerElement.querySelector(".suffix"),
93
+ this.currentValue.suffix,
94
+ gettext("Suffix")
95
+ )
96
+ this.fields.suffix.init()
97
+ }
98
+
99
+ drawOrganizationForm() {
100
+ this.fields = {}
101
+ this.typeSwitch.innerElement.innerHTML = `<div class='literal-text field-part field-part-single'></div>`
102
+ this.fields["literal"] = new LiteralFieldForm(
103
+ this.typeSwitch.innerElement.querySelector(".literal-text"),
104
+ this.currentValue.literal,
105
+ gettext("Organization name")
106
+ )
107
+ this.fields.literal.init()
108
+ }
109
+
110
+ get value() {
111
+ if (this.realPerson) {
112
+ if (
113
+ !this.fields.family.value &&
114
+ !this.fields.given.value &&
115
+ !this.fields.prefix.value &&
116
+ !this.fields.suffix.value
117
+ ) {
118
+ return false
119
+ }
120
+ const returnObject = {
121
+ family: this.fields.family.value
122
+ ? this.fields.family.value
123
+ : [],
124
+ given: this.fields.given.value ? this.fields.given.value : []
125
+ }
126
+ if (this.fields.prefix.value) {
127
+ returnObject["prefix"] = this.fields.prefix.value
128
+ returnObject["useprefix"] =
129
+ this.typeSwitch.innerElement.querySelector(
130
+ "input.useprefix"
131
+ ).checked
132
+ ? true
133
+ : false
134
+ }
135
+ if (this.fields.suffix.value) {
136
+ returnObject["suffix"] = this.fields.suffix.value
137
+ }
138
+ return returnObject
139
+ } else {
140
+ if (!this.fields.literal.value) {
141
+ return false
142
+ }
143
+ return {
144
+ literal: this.fields.literal.value
145
+ }
146
+ }
147
+ }
148
+
149
+ check() {
150
+ return true
151
+ }
152
+ }
@@ -0,0 +1,42 @@
1
+ import {InputList} from "fwtoolkit"
2
+ import {NameFieldForm} from "./name"
3
+
4
+ export class NameListForm {
5
+ constructor(dom, initialValue = [[]]) {
6
+ this.dom = dom
7
+ this.fieldHandlers = new WeakMap()
8
+ this.inputList = new InputList({
9
+ dom,
10
+ initialValues: initialValue,
11
+ emptyValue: [],
12
+ renderItem: value => ({
13
+ html: `<div class="name-field"></div>`,
14
+ bind: el => {
15
+ const fieldHandler = new NameFieldForm(
16
+ el.firstElementChild,
17
+ value
18
+ )
19
+ fieldHandler.init()
20
+ this.fieldHandlers.set(el, fieldHandler)
21
+ }
22
+ }),
23
+ getValue: el => this.fieldHandlers.get(el).value
24
+ })
25
+ }
26
+
27
+ init() {
28
+ // InputList is already rendered by the constructor.
29
+ }
30
+
31
+ get value() {
32
+ const formValue = this.inputList.values.filter(value => value !== false)
33
+ if (formValue.length === 0) {
34
+ return false
35
+ }
36
+ return formValue
37
+ }
38
+
39
+ check() {
40
+ return true
41
+ }
42
+ }
@@ -0,0 +1,104 @@
1
+ import {TypeSwitch, getFocusIndex, setFocusIndex} from "fwtoolkit"
2
+ import {LiteralFieldForm} from "./literal"
3
+
4
+ // There are only range lists, no range fields in the data format. The separation
5
+ // between RangeFieldForm and RangeListForm is for keeping consistency with other fields
6
+ // and lists.
7
+
8
+ export class RangeFieldForm {
9
+ constructor(dom, initialValue = [[]]) {
10
+ this.currentValue = initialValue
11
+ this.dom = dom
12
+ // We set the mode based on whether there is one or two initial values.
13
+ if (initialValue.length > 1) {
14
+ this.range = true
15
+ } else {
16
+ this.range = false
17
+ }
18
+ }
19
+
20
+ init() {
21
+ this.typeSwitch = new TypeSwitch({
22
+ dom: this.dom,
23
+ label1: gettext("Single value"),
24
+ label2: gettext("Range"),
25
+ initialMode: this.range ? 2 : 1,
26
+ beforeChange: () => {
27
+ const formValue = this.value
28
+ if (formValue) {
29
+ Object.assign(this.currentValue, formValue)
30
+ }
31
+ },
32
+ onChange: mode => {
33
+ this.range = mode === 2
34
+ const focusIndex = getFocusIndex()
35
+ this.drawForm()
36
+ setFocusIndex(focusIndex)
37
+ }
38
+ })
39
+ this.drawForm()
40
+ }
41
+
42
+ drawForm() {
43
+ if (this.range) {
44
+ this.drawRangeForm()
45
+ } else {
46
+ this.drawSingleValueForm()
47
+ }
48
+ }
49
+
50
+ drawSingleValueForm() {
51
+ this.fields = {}
52
+ this.typeSwitch.innerElement.innerHTML = `<div class='single-value field-part field-part-single'></div>`
53
+ this.fields["single"] = new LiteralFieldForm(
54
+ this.typeSwitch.innerElement.querySelector(".single-value"),
55
+ this.currentValue[0]
56
+ )
57
+ this.fields.single.init()
58
+ }
59
+
60
+ drawRangeForm() {
61
+ this.fields = {}
62
+ this.typeSwitch.innerElement.innerHTML = `
63
+ <div class='range-from field-part field-part-huge'></div>
64
+ <div class='range-to field-part field-part-huge'></div>
65
+ `
66
+ this.fields["from"] = new LiteralFieldForm(
67
+ this.typeSwitch.innerElement.querySelector(".range-from"),
68
+ this.currentValue[0],
69
+ gettext("From")
70
+ )
71
+ this.fields.from.init()
72
+ this.fields["to"] = new LiteralFieldForm(
73
+ this.typeSwitch.innerElement.querySelector(".range-to"),
74
+ this.currentValue[1],
75
+ gettext("To")
76
+ )
77
+ this.fields.to.init()
78
+ }
79
+
80
+ get value() {
81
+ if (this.range) {
82
+ if (!this.fields.from.value && !this.fields.to.value) {
83
+ return false
84
+ }
85
+ return [
86
+ this.fields.from.value
87
+ ? this.fields.from.value
88
+ : [{type: "text", text: ""}],
89
+ this.fields.to.value
90
+ ? this.fields.to.value
91
+ : [{type: "text", text: ""}]
92
+ ]
93
+ } else {
94
+ if (!this.fields.single.value) {
95
+ return false
96
+ }
97
+ return [this.fields.single.value]
98
+ }
99
+ }
100
+
101
+ check() {
102
+ return true
103
+ }
104
+ }