viur-ui 0.0.1

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 (114) hide show
  1. package/README.md +79 -0
  2. package/index.d.ts +351 -0
  3. package/index.js +46 -0
  4. package/package.json +84 -0
  5. package/src/components/Browser/Browser.vue +496 -0
  6. package/src/components/Browser/TreeNav.vue +408 -0
  7. package/src/components/Browser/ViurBrowser.d.vue.ts +64 -0
  8. package/src/components/Browser/ViurBrowser.vue +271 -0
  9. package/src/components/Browser/dragSession.ts +134 -0
  10. package/src/components/Browser/index.ts +14 -0
  11. package/src/components/Browser/types.ts +30 -0
  12. package/src/components/DataTable/ColumnFilterPanel.vue +225 -0
  13. package/src/components/DataTable/DataTable.vue +3155 -0
  14. package/src/components/DataTable/ViurDataTable.d.vue.ts +72 -0
  15. package/src/components/DataTable/ViurDataTable.vue +331 -0
  16. package/src/components/DataTable/columns.ts +400 -0
  17. package/src/components/DataTable/index.ts +60 -0
  18. package/src/components/DataTable/rows.ts +446 -0
  19. package/src/components/DataTable/types.ts +267 -0
  20. package/src/components/DataTable/useColumnLayout.ts +294 -0
  21. package/src/components/DataTable/useGridNavigation.ts +193 -0
  22. package/src/components/DataTable/useVirtualRows.ts +126 -0
  23. package/src/components/DataTable/viurColumns.ts +330 -0
  24. package/src/forms/ViForm.d.vue.ts +106 -0
  25. package/src/forms/ViForm.vue +592 -0
  26. package/src/forms/ViFormCategory.vue +57 -0
  27. package/src/forms/bones/Bone.vue +1023 -0
  28. package/src/forms/bones/BoneActions.vue +127 -0
  29. package/src/forms/bones/BoneLabel.vue +122 -0
  30. package/src/forms/bones/BoneMultipleList.vue +91 -0
  31. package/src/forms/bones/BoneMultipleWrapper.vue +105 -0
  32. package/src/forms/bones/BoneNestedWrapper.vue +155 -0
  33. package/src/forms/bones/BoneSingleEntry.vue +51 -0
  34. package/src/forms/bones/FilterBone.vue +694 -0
  35. package/src/forms/bones/actionbar/defaultBar.vue +98 -0
  36. package/src/forms/bones/actionbar/fileBar.vue +165 -0
  37. package/src/forms/bones/actionbar/relationalBar.vue +125 -0
  38. package/src/forms/bones/actions/ActionDialog.vue +70 -0
  39. package/src/forms/bones/actions/Debug.vue +106 -0
  40. package/src/forms/bones/actions/Delete.vue +13 -0
  41. package/src/forms/bones/actions/DescribeImage.vue +201 -0
  42. package/src/forms/bones/actions/Download.vue +27 -0
  43. package/src/forms/bones/actions/Placeholder.vue +14 -0
  44. package/src/forms/bones/actions/Translation.vue +238 -0
  45. package/src/forms/bones/actions/index.js +280 -0
  46. package/src/forms/bones/bone.d.ts +45 -0
  47. package/src/forms/bones/country_information.json +779 -0
  48. package/src/forms/bones/index.js +225 -0
  49. package/src/forms/bones/uploadAdapter.js +46 -0
  50. package/src/forms/bones/utils.js +284 -0
  51. package/src/forms/bones/view/base_item.vue +35 -0
  52. package/src/forms/bones/view/boneLogic.js +202 -0
  53. package/src/forms/bones/view/index.js +5 -0
  54. package/src/forms/bones/widgets/booleanBone.vue +83 -0
  55. package/src/forms/bones/widgets/booleanBoneChoose.vue +57 -0
  56. package/src/forms/bones/widgets/booleanBoneSelect.vue +58 -0
  57. package/src/forms/bones/widgets/codeBone.vue +214 -0
  58. package/src/forms/bones/widgets/colorBone.vue +75 -0
  59. package/src/forms/bones/widgets/dateBone.vue +114 -0
  60. package/src/forms/bones/widgets/emailBone.vue +100 -0
  61. package/src/forms/bones/widgets/fileBone.vue +273 -0
  62. package/src/forms/bones/widgets/jsonBone.vue +63 -0
  63. package/src/forms/bones/widgets/keyBone.vue +71 -0
  64. package/src/forms/bones/widgets/numericBone.vue +125 -0
  65. package/src/forms/bones/widgets/passwordBone.vue +215 -0
  66. package/src/forms/bones/widgets/phoneBone.vue +173 -0
  67. package/src/forms/bones/widgets/rawBone.vue +94 -0
  68. package/src/forms/bones/widgets/recordBone.vue +64 -0
  69. package/src/forms/bones/widgets/relationalBone.vue +164 -0
  70. package/src/forms/bones/widgets/relationalBoneSelect.vue +120 -0
  71. package/src/forms/bones/widgets/selectBone.vue +122 -0
  72. package/src/forms/bones/widgets/selectBoneChoose.vue +104 -0
  73. package/src/forms/bones/widgets/spatialBone.vue +111 -0
  74. package/src/forms/bones/widgets/stringBone.vue +139 -0
  75. package/src/forms/bones/widgets/textBone.vue +641 -0
  76. package/src/forms/install.d.ts +4 -0
  77. package/src/forms/install.js +43 -0
  78. package/src/forms/layouts/LayloutList2Columns.vue +57 -0
  79. package/src/forms/layouts/LayoutCategory.vue +38 -0
  80. package/src/forms/layouts/LayoutList.vue +31 -0
  81. package/src/forms/utils.js +601 -0
  82. package/src/public/assets/icons/fontawesome-manifest.json +8 -0
  83. package/src/public/assets/icons/regular/file.svg +1 -0
  84. package/src/public/assets/icons/solid/arrows-left-right.svg +1 -0
  85. package/src/public/assets/icons/solid/bug.svg +1 -0
  86. package/src/public/assets/icons/solid/check.svg +1 -0
  87. package/src/public/assets/icons/solid/circle-info.svg +1 -0
  88. package/src/public/assets/icons/solid/compress.svg +1 -0
  89. package/src/public/assets/icons/solid/download.svg +1 -0
  90. package/src/public/assets/icons/solid/expand.svg +1 -0
  91. package/src/public/assets/icons/solid/grip-vertical.svg +1 -0
  92. package/src/public/assets/icons/solid/plus.svg +1 -0
  93. package/src/public/assets/icons/solid/question.svg +1 -0
  94. package/src/public/assets/icons/solid/triangle-exclamation.svg +1 -0
  95. package/src/public/assets/icons/solid/upload.svg +1 -0
  96. package/src/public/assets/icons/solid/xmark.svg +1 -0
  97. package/src/request/cache.js +183 -0
  98. package/src/request/configStore.js +516 -0
  99. package/src/request/envelope.js +211 -0
  100. package/src/request/index.js +35 -0
  101. package/src/request/messageStore.js +201 -0
  102. package/src/request/request.js +752 -0
  103. package/src/request/skel.js +90 -0
  104. package/src/theme/colorStore.js +168 -0
  105. package/src/translations/de.js +178 -0
  106. package/src/translations/en.js +177 -0
  107. package/src/user/LoginScreen.d.vue.ts +54 -0
  108. package/src/user/LoginScreen.vue +627 -0
  109. package/src/user/google.js +75 -0
  110. package/src/user/index.js +3 -0
  111. package/src/user/store.d.ts +59 -0
  112. package/src/user/store.js +183 -0
  113. package/src/webawesomeCompat.css +72 -0
  114. package/src/webawesomeConfig.js +61 -0
@@ -0,0 +1,164 @@
1
+ <template>
2
+ <div
3
+ class="bone-widget-record bone-widget bone-widget-relational bone-widget-relational-default"
4
+ :class="[`bone-widget-relational-${name}`]"
5
+ >
6
+ <div class="bone-widget-single-entry">
7
+ <wa-input
8
+ v-if="state.selection?.['dest']?.['key']"
9
+ :disabled="true"
10
+ :value="value ? formatString(state.format, state.selection) : ''"
11
+ ></wa-input>
12
+ <wa-combobox
13
+ v-else
14
+ :disabled="boneState.readonly"
15
+ :source="getList"
16
+ :placeholder="state.placeholder"
17
+ :data-user-invalid="boneState.errorMessages.length === 0 ? undefined : true"
18
+ @change="changeEvent"
19
+ ></wa-combobox>
20
+ </div>
21
+ <Wrapper_nested
22
+ v-if="bone['using']"
23
+ :value="value?.['rel']"
24
+ :name="name"
25
+ :index="index"
26
+ :lang="lang"
27
+ :bone="bone"
28
+ :disabled="bone['readonly']"
29
+ @change="changeEventNested"
30
+ ></Wrapper_nested>
31
+ </div>
32
+ </template>
33
+
34
+ <script setup>
35
+ import { reactive, onMounted, inject, computed, watch } from "vue"
36
+ import { useListFetch } from "../../../request/index.js"
37
+ import Wrapper_nested from "../BoneNestedWrapper.vue"
38
+ /**
39
+ * Relational-Auswahl-Widget für Bones vom Typ `relational` und `relational.select`.
40
+ *
41
+ * Beim Typ `relational` wird eine `<wa-combobox>` angezeigt, die via `getList`
42
+ * Einträge aus dem konfigurierten `module` lädt und filtert. Ist ein Wert gesetzt,
43
+ * wird stattdessen ein gesperrtes `<wa-input>` mit dem formatierten Eintrag angezeigt.
44
+ * Beim Typ `relational.select` wird ein Dropdown-Widget gerendert.
45
+ * Falls die Struktur ein `using`-Objekt enthält, wird zusätzlich ein `Wrapper_nested`
46
+ * für die relationalen Zusatz-Felder (`rel`) eingeblendet.
47
+ *
48
+ * @displayName RelationalBone
49
+ *
50
+ * @cssClass bone-widget-record - Äußerer Container des Widgets
51
+ * @cssClass bone-widget - Basis-Klasse aller Bone-Widgets
52
+ * @cssClass bone-widget-relational - Kennzeichnet den Bone-Typ
53
+ * @cssClass bone-widget-relational-default - Standard-Variante
54
+ * @cssClass bone-widget-relational-{name} - Dynamisch gesetzt auf den Bone-Namen
55
+ * @cssClass bone-widget-single-entry - Zeile mit Combobox/Input
56
+ */
57
+ defineOptions({
58
+ inheritAttrs: false,
59
+ })
60
+ const props = defineProps({
61
+ /** Bone-Name – wird in jedem `change`-Event als erstes Argument übergeben. */
62
+ name: String,
63
+ /** Aktueller Bone-Wert; Objekt mit `dest`- und `rel`-Schlüsseln oder `null`. */
64
+ value: [Object, String, Number, Boolean, Array],
65
+ /** Index im Multiple-Array; `undefined` bei Einzelwert. */
66
+ index: Number,
67
+ /** Sprach-Key bei mehrsprachigen Bones, z.B. `"de"`. */
68
+ lang: String,
69
+ /** Bone-Struktur; `using` steuert ob ein Nested-Wrapper angezeigt wird. */
70
+ bone: Object,
71
+ /** Aktuell nicht genutzt. */
72
+ autofocus: Boolean,
73
+ })
74
+
75
+ const emit = defineEmits([
76
+ /**
77
+ * Wird bei Auswahl eines Eintrags, beim Löschen und beim Mount (Initialisierung) gefeuert.
78
+ * @arg {string} name - Bone-Name
79
+ * @arg {{ dest: object, rel: object|null }|string} value - Ausgewähltes Relational-Objekt oder `""` beim Löschen
80
+ * @arg {string|undefined} lang - Sprach-Key
81
+ * @arg {number|undefined} index - Index im Multiple-Array
82
+ */
83
+ "change",
84
+ ])
85
+
86
+ const boneState = inject("boneState")
87
+ const formatString = inject("formatString")
88
+ const state = reactive({
89
+ format: computed(() => {
90
+ return boneState?.bonestructure["format"]
91
+ }),
92
+ skellistdata: null,
93
+ selection: null,
94
+ relationalData: null,
95
+ placeholder: computed(() => {
96
+ if (boneState.label !== "placeholder") return undefined
97
+ let name = boneState?.bonestructure?.descr
98
+ if (boneState.bonestructure.required) {
99
+ name += "*"
100
+ }
101
+ return name
102
+ }),
103
+ })
104
+
105
+ async function getList(search) {
106
+ let params = { limit: 99 }
107
+ if (boneState.bonestructure["type"] === "relational.tree.leaf.file") {
108
+ params.skelType = "leaf"
109
+ } else if (boneState.bonestructure["type"] === "relational.tree.node.file") {
110
+ params.skelType = "node"
111
+ }
112
+
113
+ const listFetch = useListFetch(boneState.bonestructure["module"], {
114
+ immediate: false,
115
+ params,
116
+ renderer: import.meta.env.VITE_DEFAULT_RENDERER || "vi",
117
+ })
118
+
119
+ await listFetch.execute()
120
+
121
+ //?viurTags$lk=${search.toLowerCase()
122
+ const data = { skellist: listFetch.data.value }
123
+
124
+ state.skellistdata = {}
125
+ for (let e of data["skellist"]) {
126
+ state.skellistdata[e["key"]] = e
127
+ }
128
+
129
+ return data["skellist"]?.map((d) => {
130
+ return { text: formatString(boneState.bonestructure["format"], { dest: d }), value: d.key, data: d }
131
+ })
132
+ }
133
+
134
+ function changeEvent(event) {
135
+ state.selection = { dest: state.skellistdata[event.target.value] }
136
+ if (props.bone["using"] && state.relationalData) {
137
+ state.selection = { ...state.selection, rel: state.relationalData }
138
+ }
139
+ emit("change", props.name, state.selection, props.lang, props.index)
140
+ }
141
+
142
+ function changeEventNested(data) {
143
+ state.relationalData = data["value"]
144
+ if (state.selection?.dest) {
145
+ // only send a change if we have a valid target
146
+ state.selection = { ...props.value, rel: data["value"] }
147
+ emit("change", data["name"], state.selection, data["lang"], data["index"])
148
+ }
149
+ }
150
+
151
+ // Halte state.selection synchron mit props.value — wichtig, wenn der Wert
152
+ // von außen geleert wird (z.B. via Delete-Action).
153
+ watch(
154
+ () => props.value,
155
+ (newVal) => {
156
+ state.selection = newVal || null
157
+ }
158
+ )
159
+
160
+ onMounted(() => {
161
+ state.selection = props.value
162
+ emit("change", props.name, props.value, props.lang, props.index) //init
163
+ })
164
+ </script>
@@ -0,0 +1,120 @@
1
+ <template>
2
+ <div
3
+ class="bone-widget-record bone-widget bone-widget-relational bone-widget-relational-select"
4
+ :class="[`bone-widget-relational-${name}`]"
5
+ >
6
+ <div class="bone-widget-single-entry">
7
+ <wa-select
8
+ :disabled="boneState.readonly"
9
+ :value="state.selection?.['dest']['key']"
10
+ max-options-visible="0"
11
+ with-clear
12
+ :required="
13
+ boneState.bonestructure.required && !boneState.bonestructure.multiple && !boneState.bonestructure.languages
14
+ "
15
+ :placeholder="state.placeholder"
16
+ :data-user-invalid="boneState.errorMessages.length === 0 ? undefined : true"
17
+ @change="changeEvent"
18
+ >
19
+ <wa-option
20
+ v-for="(obj, key) in state.skellistdata"
21
+ :key="key"
22
+ :value="key"
23
+ >
24
+ {{ formatString(state.format, obj) }}
25
+ </wa-option>
26
+ </wa-select>
27
+ </div>
28
+ <Wrapper_nested
29
+ v-if="bone['using']"
30
+ :value="value"
31
+ :name="name"
32
+ :index="index"
33
+ :bone="bone"
34
+ :disabled="bone['readonly']"
35
+ @change="changeEventNested"
36
+ ></Wrapper_nested>
37
+ </div>
38
+ </template>
39
+
40
+ <script setup>
41
+ import { reactive, onMounted, inject, computed } from "vue"
42
+ import { useListFetch } from "../../../request/index.js"
43
+ import Wrapper_nested from "../BoneNestedWrapper.vue"
44
+ defineOptions({
45
+ inheritAttrs: false,
46
+ })
47
+ const props = defineProps({
48
+ name: String,
49
+ value: [Object, String, Number, Boolean, Array],
50
+ index: Number,
51
+ lang: String,
52
+ bone: Object,
53
+ autofocus: Boolean,
54
+ })
55
+
56
+ const emit = defineEmits(["change"])
57
+
58
+ const boneState = inject("boneState")
59
+ const formatString = inject("formatString")
60
+ const state = reactive({
61
+ format: computed(() => {
62
+ return boneState?.bonestructure["format"]
63
+ }),
64
+ skellistdata: null,
65
+ selection: null,
66
+ placeholder: computed(() => {
67
+ if (boneState.label !== "placeholder") return undefined
68
+ let name = boneState?.bonestructure?.descr
69
+ if (boneState.bonestructure.required) {
70
+ name += "*"
71
+ }
72
+ return name
73
+ }),
74
+ })
75
+
76
+ async function getList(search) {
77
+ let params = { limit: 99 }
78
+ if (boneState.bonestructure["type"] === "relational.tree.leaf.file") {
79
+ params.skelType = "leaf"
80
+ } else if (boneState.bonestructure["type"] === "relational.tree.node.file") {
81
+ params.skelType = "node"
82
+ }
83
+
84
+ const listFetch = useListFetch(boneState.bonestructure["module"], {
85
+ immediate: false,
86
+ params,
87
+ renderer: import.meta.env.VITE_DEFAULT_RENDERER || "vi",
88
+ })
89
+
90
+ await listFetch.execute()
91
+
92
+ //?viurTags$lk=${search.toLowerCase()
93
+ const data = { skellist: listFetch.data.value }
94
+
95
+ state.skellistdata = {}
96
+ for (let e of data["skellist"]) {
97
+ state.skellistdata[e["key"]] = e
98
+ }
99
+
100
+ return data["skellist"]?.map((d) => {
101
+ return { text: formatString(boneState.bonestructure["format"], { dest: d }), value: d.key, data: d }
102
+ })
103
+ }
104
+
105
+ function changeEvent(event) {
106
+ state.selection = { dest: state.skellistdata[event.target.value] }
107
+ emit("change", props.name, state.selection, props.lang, props.index)
108
+ }
109
+
110
+ function changeEventNested(data) {
111
+ state.selection = { ...state.selection, rel: data["value"] }
112
+ emit("change", data["name"], state.selection, data["lang"], data["index"])
113
+ }
114
+
115
+ onMounted(() => {
116
+ state.selection = props.value
117
+ getList()
118
+ emit("change", props.name, props.value, props.lang, props.index) //init
119
+ })
120
+ </script>
@@ -0,0 +1,122 @@
1
+ <template>
2
+ <wa-select
3
+ class="bone-widget bone-widget-select bone-widget-select-default"
4
+ :class="[`bone-widget-select-${name}`]"
5
+ :name="name"
6
+ :disabled="boneState.readonly"
7
+ :value="state.value"
8
+ :multiple="boneState['bonestructure']['multiple']"
9
+ max-options-visible="0"
10
+ :required="boneState.bonestructure.required"
11
+ with-clear
12
+ :placeholder="state.placeholder"
13
+ :data-user-invalid="boneState.errorMessages.length === 0 ? undefined : true"
14
+ @change="changeEvent"
15
+ >
16
+ <wa-option
17
+ v-for="value in convertObjToList()"
18
+ :key="value[0]"
19
+ :value="value[0]"
20
+ >
21
+ {{ value[1] }}
22
+ </wa-option>
23
+ </wa-select>
24
+ </template>
25
+
26
+ <script setup>
27
+ import { reactive, onMounted, inject, computed } from "vue"
28
+ /**
29
+ * Dropdown-Auswahlfeld für vordefinierte Werte (Typ `select`).
30
+ *
31
+ * Rendert ein `<wa-select>` mit `<wa-option>`-Einträgen, die aus
32
+ * `boneState.bonestructure.values` generiert werden. `values` kann ein Array
33
+ * von `[key, label]`-Tupeln oder ein Objekt `{ key: label }` sein.
34
+ * Bei aktiviertem `multiple` können mehrere Optionen gleichzeitig gewählt werden.
35
+ * Der Bone-Typ `select.choose` wird durch die separate Komponente `SelectBoneChoose`
36
+ * abgehandelt und rendert Radio-Buttons bzw. Checkboxen.
37
+ * Bei `boneState.label === "placeholder"` wird der Bone-Name als Placeholder angezeigt.
38
+ *
39
+ * @displayName SelectBone
40
+ *
41
+ * @cssClass bone-widget - Basis-Klasse aller Bone-Widgets
42
+ * @cssClass bone-widget-select - Kennzeichnet den Bone-Typ
43
+ * @cssClass bone-widget-select-default - Standard-Variante (Dropdown)
44
+ * @cssClass bone-widget-select-{name} - Dynamisch gesetzt auf den Bone-Namen, z.B. `bone-widget-select-status`
45
+ */
46
+ defineOptions({
47
+ inheritAttrs: false,
48
+ })
49
+ const props = defineProps({
50
+ /** Bone-Name – wird in jedem `change`-Event als erstes Argument übergeben. */
51
+ name: String,
52
+ /** Aktueller Bone-Wert (String, Array bei multiple). */
53
+ value: null,
54
+ /** Index im Multiple-Array; `undefined` bei Einzelwert. */
55
+ index: Number,
56
+ /** Sprach-Key bei mehrsprachigen Bones, z.B. `"de"`. */
57
+ lang: String,
58
+ /** Bone-Struktur (aktuell nicht aktiv genutzt). */
59
+ bone: Object,
60
+ /** Setzt den Fokus auf das Select-Element (aktuell nicht implementiert). */
61
+ autofocus: Boolean,
62
+ })
63
+
64
+ const emit = defineEmits([
65
+ /**
66
+ * Wird bei jeder Wertänderung sowie beim Mount (Initialisierung) gefeuert.
67
+ * @arg {string} name - Bone-Name
68
+ * @arg {string|string[]} value - Gewählter Wert oder Array bei multiple
69
+ * @arg {string|undefined} lang - Sprach-Key
70
+ * @arg {number|undefined} index - Index im Multiple-Array
71
+ */
72
+ "change",
73
+ ])
74
+
75
+ const boneState = inject("boneState")
76
+ const state = reactive({
77
+ value: computed(() => {
78
+ let val = props.value
79
+ if (Array.isArray(props.value)) {
80
+ if (boneState["bonestructure"]["values"] instanceof Array) {
81
+ val = val.filter((i) => boneState["bonestructure"]["values"].map((i) => i[0].toString()).includes(i))
82
+ } else
83
+ val = val.filter((i) =>
84
+ Object.keys(boneState["bonestructure"]["values"])
85
+ .map((i) => i.toString())
86
+ .includes(i)
87
+ )
88
+
89
+ return val.map((i) => i.toString())
90
+ }
91
+ return props.value ? props.value.toString() : ""
92
+ }),
93
+ placeholder: computed(() => {
94
+ if (boneState.label !== "placeholder") return undefined
95
+ let name = boneState?.bonestructure?.descr
96
+ if (boneState.bonestructure.required) {
97
+ name += "*"
98
+ }
99
+ return name
100
+ }),
101
+ })
102
+
103
+ function convertObjToList() {
104
+ if (Array.isArray(boneState["bonestructure"]["values"])) {
105
+ return boneState["bonestructure"]["values"]
106
+ } else {
107
+ let objToList = []
108
+ for (const [key, value] of Object.entries(boneState["bonestructure"]["values"])) {
109
+ objToList.push([key, value])
110
+ }
111
+ return objToList
112
+ }
113
+ }
114
+
115
+ function changeEvent(event) {
116
+ emit("change", props.name, event.target.value, props.lang, props.index)
117
+ }
118
+
119
+ onMounted(() => {
120
+ emit("change", props.name, state.value, props.lang, props.index) //init
121
+ })
122
+ </script>
@@ -0,0 +1,104 @@
1
+ <template>
2
+ <div
3
+ v-if="boneState['bonestructure']['multiple']"
4
+ class="bone-widget-multiple-wrapper bone-widget bone-widget-select bone-widget-select-choose"
5
+ :class="[`bone-widget-select-${name}`]"
6
+ >
7
+ <wa-checkbox
8
+ v-for="value in convertObjToList()"
9
+ :data-value="value[0]"
10
+ :checked="state.value.includes(value[0])"
11
+ :disabled="boneState.readonly"
12
+ :data-user-invalid="boneState.errorMessages.length === 0 ? undefined : true"
13
+ @change="changeEventMultiple"
14
+ >
15
+ {{ value[1] }}
16
+ </wa-checkbox>
17
+ </div>
18
+
19
+ <!-- readonly an der Gruppe (siehe booleanBoneChoose): disabled Radios
20
+ zeigten keine Auswahl -->
21
+ <wa-radio-group
22
+ v-else
23
+ :value="state.value"
24
+ :disabled="boneState.readonly"
25
+ class="bone-widget bone-widget-select bone-widget-select-choose"
26
+ :class="[`bone-widget-select-${name}`]"
27
+ @change="changeEvent"
28
+ >
29
+ <wa-radio
30
+ v-for="value in convertObjToList()"
31
+ :value="value[0]"
32
+ :data-user-invalid="boneState.errorMessages.length === 0 ? undefined : true"
33
+ >
34
+ {{ value[1] }}
35
+ </wa-radio>
36
+ </wa-radio-group>
37
+ </template>
38
+
39
+ <script setup>
40
+ import { reactive, onMounted, inject, computed } from "vue"
41
+ defineOptions({
42
+ inheritAttrs: false,
43
+ })
44
+ const props = defineProps({
45
+ name: String,
46
+ value: null,
47
+ index: Number,
48
+ lang: String,
49
+ bone: Object,
50
+ autofocus: Boolean,
51
+ })
52
+
53
+ const emit = defineEmits(["change"])
54
+
55
+ const boneState = inject("boneState")
56
+ const state = reactive({
57
+ value: computed(() => {
58
+ let val = props.value
59
+ if (Array.isArray(props.value)) {
60
+ if (boneState["bonestructure"]["values"] instanceof Array) {
61
+ val = val.filter((i) => boneState["bonestructure"]["values"].map((i) => i[0].toString()).includes(i))
62
+ } else
63
+ val = val.filter((i) =>
64
+ Object.keys(boneState["bonestructure"]["values"])
65
+ .map((i) => i.toString())
66
+ .includes(i)
67
+ )
68
+
69
+ return val.map((i) => i.toString())
70
+ }
71
+ return props.value ? props.value.toString() : ""
72
+ }),
73
+ })
74
+
75
+ function convertObjToList() {
76
+ if (Array.isArray(boneState["bonestructure"]["values"])) {
77
+ return boneState["bonestructure"]["values"]
78
+ } else {
79
+ let objToList = []
80
+ for (const [key, value] of Object.entries(boneState["bonestructure"]["values"])) {
81
+ objToList.push([key, value])
82
+ }
83
+ return objToList
84
+ }
85
+ }
86
+
87
+ function changeEventMultiple(event) {
88
+ let currentValue = [...state.value]
89
+ if (event.target.checked) {
90
+ currentValue.push(event.target.dataset["value"])
91
+ } else {
92
+ currentValue = currentValue.filter((x) => x !== event.target.dataset["value"])
93
+ }
94
+ emit("change", props.name, currentValue, props.lang, props.index)
95
+ }
96
+
97
+ function changeEvent(event) {
98
+ emit("change", props.name, event.target.value, props.lang, props.index)
99
+ }
100
+
101
+ onMounted(() => {
102
+ emit("change", props.name, state.value, props.lang, props.index) //init
103
+ })
104
+ </script>
@@ -0,0 +1,111 @@
1
+ <template>
2
+ <div class="wa-stack wa-gap-xs">
3
+ <wa-input
4
+ v-model="state.valueLat"
5
+ class="bone-widget bone-widget-spatial bone-widget-spatial-default"
6
+ :class="([`bone-widget-spatial-${name}`], [`bone-widget-spatial-${name}-lat`])"
7
+ index="lat"
8
+ type="number"
9
+ :name="name"
10
+ :min="boneState.bonestructure.boundslat[0]"
11
+ :max="boneState.bonestructure.boundslat[1]"
12
+ :disabled="boneState.readonly"
13
+ value-as-number
14
+ step="0.000001"
15
+ :placeholder="state.placeholder"
16
+ :data-user-invalid="boneState.errorMessages.length === 0 ? undefined : true"
17
+ @change="changeEvent"
18
+ ></wa-input>
19
+
20
+ <wa-input
21
+ v-model="state.valueLng"
22
+ class="bone-widget bone-widget-spatial bone-widget-spatial-default"
23
+ :class="([`bone-widget-spatial-${name}`], [`bone-widget-spatial-${name}-long`])"
24
+ index="lng"
25
+ type="number"
26
+ :name="name"
27
+ :min="boneState.bonestructure.boundslng[0]"
28
+ :max="boneState.bonestructure.boundslng[1]"
29
+ :disabled="boneState.readonly"
30
+ value-as-number
31
+ step="0.000001"
32
+ :placeholder="state.placeholder"
33
+ :data-user-invalid="boneState.errorMessages.length === 0 ? undefined : true"
34
+ @change="changeEvent"
35
+ ></wa-input>
36
+ </div>
37
+ </template>
38
+
39
+ <script setup>
40
+ import { reactive, onMounted, inject, computed } from "vue"
41
+ /**
42
+ * Koordinaten-Eingabe für geografische Punkte (Breitengrad / Längengrad).
43
+ *
44
+ * Rendert zwei `<wa-input type="number">` Felder für Latitude und Longitude.
45
+ * Die erlaubten Wertebereiche werden über `boneState.bonestructure.boundslat`
46
+ * und `boneState.bonestructure.boundslng` gesteuert. Unterstützt weder
47
+ * Mehrsprachigkeit noch Mehrfachwerte.
48
+ *
49
+ * @displayName SpatialBone
50
+ *
51
+ * @cssClass bone-widget - Basis-Klasse aller Bone-Widgets
52
+ * @cssClass bone-widget-spatial - Kennzeichnet den Bone-Typ
53
+ * @cssClass bone-widget-spatial-default - Standard-Variante
54
+ * @cssClass bone-widget-spatial-{name}-lat - Dynamisch gesetzt für das Breiten­grad-Feld
55
+ * @cssClass bone-widget-spatial-{name}-long - Dynamisch gesetzt für das Längen­grad-Feld
56
+ */
57
+ defineOptions({
58
+ inheritAttrs: false,
59
+ })
60
+ const props = defineProps({
61
+ /** Bone-Name – wird in jedem `change`-Event als erstes Argument übergeben. */
62
+ name: String,
63
+ /** Aktueller Bone-Wert als Array `[lat, lng]` oder Objekt `{ lat, lng }`. */
64
+ value: [Object, String, Number, Boolean, Array],
65
+ /** Index im Multiple-Array; `undefined` bei Einzelwert. */
66
+ index: Number,
67
+ /** Sprach-Key (SpatialBone unterstützt kein multilang). */
68
+ lang: String,
69
+ /** Bone-Struktur (aktuell nicht aktiv genutzt). */
70
+ bone: Object,
71
+ /** Setzt den Fokus nach dem Mount auf das erste Input-Element. */
72
+ autofocus: Boolean,
73
+ })
74
+
75
+ const emit = defineEmits([
76
+ /**
77
+ * Wird bei jeder Wertänderung sowie beim Mount (Initialisierung) gefeuert.
78
+ * @arg {string} name - Bone-Name
79
+ * @arg {[number, number]} value - Koordinaten als `[lat, lng]`
80
+ * @arg {string|undefined} lang - Sprach-Key
81
+ * @arg {number|undefined} index - Index im Multiple-Array
82
+ */
83
+ "change",
84
+ ])
85
+
86
+ const boneState = inject("boneState")
87
+ const state = reactive({
88
+ valueLat: null,
89
+ valueLng: null,
90
+ placeholder: computed(() => {
91
+ if (boneState.label !== "placeholder") return undefined
92
+ let name = boneState?.bonestructure?.descr
93
+ if (boneState.bonestructure.required) {
94
+ name += "*"
95
+ }
96
+ return name
97
+ }),
98
+ })
99
+
100
+ function changeEvent() {
101
+ emit("change", props.name, [state.valueLat, state.valueLng], props.lang, props.index)
102
+ }
103
+
104
+ onMounted(() => {
105
+ try {
106
+ state.valueLat = props.value[0]
107
+ state.valueLng = props.value[1]
108
+ } catch (e) {}
109
+ emit("change", props.name, [state.valueLat, state.valueLng], props.lang, props.index) //init
110
+ })
111
+ </script>