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.
- package/README.md +79 -0
- package/index.d.ts +351 -0
- package/index.js +46 -0
- package/package.json +84 -0
- package/src/components/Browser/Browser.vue +496 -0
- package/src/components/Browser/TreeNav.vue +408 -0
- package/src/components/Browser/ViurBrowser.d.vue.ts +64 -0
- package/src/components/Browser/ViurBrowser.vue +271 -0
- package/src/components/Browser/dragSession.ts +134 -0
- package/src/components/Browser/index.ts +14 -0
- package/src/components/Browser/types.ts +30 -0
- package/src/components/DataTable/ColumnFilterPanel.vue +225 -0
- package/src/components/DataTable/DataTable.vue +3155 -0
- package/src/components/DataTable/ViurDataTable.d.vue.ts +72 -0
- package/src/components/DataTable/ViurDataTable.vue +331 -0
- package/src/components/DataTable/columns.ts +400 -0
- package/src/components/DataTable/index.ts +60 -0
- package/src/components/DataTable/rows.ts +446 -0
- package/src/components/DataTable/types.ts +267 -0
- package/src/components/DataTable/useColumnLayout.ts +294 -0
- package/src/components/DataTable/useGridNavigation.ts +193 -0
- package/src/components/DataTable/useVirtualRows.ts +126 -0
- package/src/components/DataTable/viurColumns.ts +330 -0
- package/src/forms/ViForm.d.vue.ts +106 -0
- package/src/forms/ViForm.vue +592 -0
- package/src/forms/ViFormCategory.vue +57 -0
- package/src/forms/bones/Bone.vue +1023 -0
- package/src/forms/bones/BoneActions.vue +127 -0
- package/src/forms/bones/BoneLabel.vue +122 -0
- package/src/forms/bones/BoneMultipleList.vue +91 -0
- package/src/forms/bones/BoneMultipleWrapper.vue +105 -0
- package/src/forms/bones/BoneNestedWrapper.vue +155 -0
- package/src/forms/bones/BoneSingleEntry.vue +51 -0
- package/src/forms/bones/FilterBone.vue +694 -0
- package/src/forms/bones/actionbar/defaultBar.vue +98 -0
- package/src/forms/bones/actionbar/fileBar.vue +165 -0
- package/src/forms/bones/actionbar/relationalBar.vue +125 -0
- package/src/forms/bones/actions/ActionDialog.vue +70 -0
- package/src/forms/bones/actions/Debug.vue +106 -0
- package/src/forms/bones/actions/Delete.vue +13 -0
- package/src/forms/bones/actions/DescribeImage.vue +201 -0
- package/src/forms/bones/actions/Download.vue +27 -0
- package/src/forms/bones/actions/Placeholder.vue +14 -0
- package/src/forms/bones/actions/Translation.vue +238 -0
- package/src/forms/bones/actions/index.js +280 -0
- package/src/forms/bones/bone.d.ts +45 -0
- package/src/forms/bones/country_information.json +779 -0
- package/src/forms/bones/index.js +225 -0
- package/src/forms/bones/uploadAdapter.js +46 -0
- package/src/forms/bones/utils.js +284 -0
- package/src/forms/bones/view/base_item.vue +35 -0
- package/src/forms/bones/view/boneLogic.js +202 -0
- package/src/forms/bones/view/index.js +5 -0
- package/src/forms/bones/widgets/booleanBone.vue +83 -0
- package/src/forms/bones/widgets/booleanBoneChoose.vue +57 -0
- package/src/forms/bones/widgets/booleanBoneSelect.vue +58 -0
- package/src/forms/bones/widgets/codeBone.vue +214 -0
- package/src/forms/bones/widgets/colorBone.vue +75 -0
- package/src/forms/bones/widgets/dateBone.vue +114 -0
- package/src/forms/bones/widgets/emailBone.vue +100 -0
- package/src/forms/bones/widgets/fileBone.vue +273 -0
- package/src/forms/bones/widgets/jsonBone.vue +63 -0
- package/src/forms/bones/widgets/keyBone.vue +71 -0
- package/src/forms/bones/widgets/numericBone.vue +125 -0
- package/src/forms/bones/widgets/passwordBone.vue +215 -0
- package/src/forms/bones/widgets/phoneBone.vue +173 -0
- package/src/forms/bones/widgets/rawBone.vue +94 -0
- package/src/forms/bones/widgets/recordBone.vue +64 -0
- package/src/forms/bones/widgets/relationalBone.vue +164 -0
- package/src/forms/bones/widgets/relationalBoneSelect.vue +120 -0
- package/src/forms/bones/widgets/selectBone.vue +122 -0
- package/src/forms/bones/widgets/selectBoneChoose.vue +104 -0
- package/src/forms/bones/widgets/spatialBone.vue +111 -0
- package/src/forms/bones/widgets/stringBone.vue +139 -0
- package/src/forms/bones/widgets/textBone.vue +641 -0
- package/src/forms/install.d.ts +4 -0
- package/src/forms/install.js +43 -0
- package/src/forms/layouts/LayloutList2Columns.vue +57 -0
- package/src/forms/layouts/LayoutCategory.vue +38 -0
- package/src/forms/layouts/LayoutList.vue +31 -0
- package/src/forms/utils.js +601 -0
- package/src/public/assets/icons/fontawesome-manifest.json +8 -0
- package/src/public/assets/icons/regular/file.svg +1 -0
- package/src/public/assets/icons/solid/arrows-left-right.svg +1 -0
- package/src/public/assets/icons/solid/bug.svg +1 -0
- package/src/public/assets/icons/solid/check.svg +1 -0
- package/src/public/assets/icons/solid/circle-info.svg +1 -0
- package/src/public/assets/icons/solid/compress.svg +1 -0
- package/src/public/assets/icons/solid/download.svg +1 -0
- package/src/public/assets/icons/solid/expand.svg +1 -0
- package/src/public/assets/icons/solid/grip-vertical.svg +1 -0
- package/src/public/assets/icons/solid/plus.svg +1 -0
- package/src/public/assets/icons/solid/question.svg +1 -0
- package/src/public/assets/icons/solid/triangle-exclamation.svg +1 -0
- package/src/public/assets/icons/solid/upload.svg +1 -0
- package/src/public/assets/icons/solid/xmark.svg +1 -0
- package/src/request/cache.js +183 -0
- package/src/request/configStore.js +516 -0
- package/src/request/envelope.js +211 -0
- package/src/request/index.js +35 -0
- package/src/request/messageStore.js +201 -0
- package/src/request/request.js +752 -0
- package/src/request/skel.js +90 -0
- package/src/theme/colorStore.js +168 -0
- package/src/translations/de.js +178 -0
- package/src/translations/en.js +177 -0
- package/src/user/LoginScreen.d.vue.ts +54 -0
- package/src/user/LoginScreen.vue +627 -0
- package/src/user/google.js +75 -0
- package/src/user/index.js +3 -0
- package/src/user/store.d.ts +59 -0
- package/src/user/store.js +183 -0
- package/src/webawesomeCompat.css +72 -0
- package/src/webawesomeConfig.js +61 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import Utils from "../utils"
|
|
2
|
+
import { computed, reactive } from "vue"
|
|
3
|
+
|
|
4
|
+
export const languageMap = [
|
|
5
|
+
{ lang: "en", country: "US", label: "English", flag: "\uD83C\uDDEC\uD83C\uDDE7" },
|
|
6
|
+
{ lang: "de", country: "DE", label: "Deutsch", flag: "\ud83c\udde9\ud83c\uddea" },
|
|
7
|
+
{ lang: "ch", country: "CH", label: "Schweiz", flag: "\ud83c\udde8\ud83c\udded" },
|
|
8
|
+
{ lang: "fr", country: "FR", label: "Français", flag: "\ud83c\uddeb\ud83c\uddf7" },
|
|
9
|
+
{ lang: "es", country: "ES", label: "Español", flag: "\ud83c\uddea\ud83c\uddf8" },
|
|
10
|
+
{ lang: "pt", country: "BR", label: "Português", flag: "\ud83c\udde7\ud83c\uddf7" },
|
|
11
|
+
{ lang: "it", country: "IT", label: "Italiano", flag: "\ud83c\uddee\ud83c\uddf9" },
|
|
12
|
+
{ lang: "nl", country: "NL", label: "Nederlands", flag: "\ud83c\uddf3\ud83c\uddf1" },
|
|
13
|
+
{ lang: "pl", country: "PL", label: "Polski", flag: "\ud83c\uddf5\ud83c\uddf1" },
|
|
14
|
+
{ lang: "ru", country: "RU", label: "Русский", flag: "\ud83c\uddf7\ud83c\uddfa" },
|
|
15
|
+
{ lang: "tr", country: "TR", label: "Türkçe", flag: "\ud83c\uddf9\ud83c\uddf7" },
|
|
16
|
+
{ lang: "zh", country: "CN", label: "中文", flag: "\ud83c\udde8\ud83c\uddf3" },
|
|
17
|
+
{ lang: "ja", country: "JP", label: "日本語", flag: "\ud83c\uddef\ud83c\uddf5" },
|
|
18
|
+
{ lang: "ko", country: "KR", label: "한국어", flag: "\ud83c\uddf0\ud83c\uddf7" },
|
|
19
|
+
{ lang: "ar", country: "SA", label: "العربية", flag: "\ud83c\uddf8\ud83c\udde6" },
|
|
20
|
+
{ lang: "hi", country: "IN", label: "हिन्दी", flag: "\ud83c\uddee\ud83c\uddf3" },
|
|
21
|
+
{ lang: "sv", country: "SE", label: "Svenska", flag: "\ud83c\uddf8\ud83c\uddea" },
|
|
22
|
+
{ lang: "no", country: "NO", label: "Norsk", flag: "\ud83c\uddf3\ud83c\uddf4" },
|
|
23
|
+
{ lang: "da", country: "DK", label: "Dansk", flag: "\ud83c\udde9\ud83c\uddf0" },
|
|
24
|
+
{ lang: "fi", country: "FI", label: "Suomi", flag: "\ud83c\uddeb\ud83c\uddee" },
|
|
25
|
+
{ lang: "cs", country: "CZ", label: "Čeština", flag: "\ud83c\udde8\ud83c\uddff" },
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
const boneLogic = (skel, structure, showflags = false, selectedLang = null, t = null) => {
|
|
29
|
+
let bones_state = reactive({
|
|
30
|
+
skel: computed(() => {
|
|
31
|
+
if (skel && skel.constructor.name === "RefImpl") {
|
|
32
|
+
return skel.value
|
|
33
|
+
}
|
|
34
|
+
return skel
|
|
35
|
+
}),
|
|
36
|
+
structure: computed(() => {
|
|
37
|
+
if (structure.constructor.name === "RefImpl") {
|
|
38
|
+
return structure.value
|
|
39
|
+
}
|
|
40
|
+
return structure
|
|
41
|
+
}),
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
function getBoneValue(boneName, options = null, skel = null) {
|
|
45
|
+
if (skel === null) {
|
|
46
|
+
skel = bones_state.skel
|
|
47
|
+
}
|
|
48
|
+
if (skel === null) {
|
|
49
|
+
return "-"
|
|
50
|
+
}
|
|
51
|
+
if (Utils.objectEmpty(skel) || Utils.objectEmpty(bones_state.structure)) {
|
|
52
|
+
return "-"
|
|
53
|
+
}
|
|
54
|
+
let languages = hasLanguages(boneName)
|
|
55
|
+
if (languages) {
|
|
56
|
+
let values = []
|
|
57
|
+
|
|
58
|
+
for (let lang of languages) {
|
|
59
|
+
if (isMultiple(boneName)) {
|
|
60
|
+
if (selectedLang) {
|
|
61
|
+
if (selectedLang === lang) {
|
|
62
|
+
values.push(langPrefix(lang, renderMultipleValue(boneName, options, skel, lang)))
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
values.push(langPrefix(lang, renderMultipleValue(boneName, options, skel, lang)))
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
if (selectedLang) {
|
|
69
|
+
if (selectedLang === lang) {
|
|
70
|
+
values.push(langPrefix(lang, renderSingleValue(boneName, options, null, skel, lang)))
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
values.push(langPrefix(lang, renderSingleValue(boneName, options, null, skel, lang)))
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return values.join(", ")
|
|
78
|
+
} else {
|
|
79
|
+
if (isMultiple(boneName)) {
|
|
80
|
+
return renderMultipleValue(boneName, options, skel, null)
|
|
81
|
+
} else {
|
|
82
|
+
return renderSingleValue(boneName, options, null, skel, null)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function hasLanguages(boneName) {
|
|
88
|
+
return bones_state.structure[boneName] && bones_state.structure[boneName]["languages"]
|
|
89
|
+
? bones_state.structure[boneName]["languages"]
|
|
90
|
+
: false
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function isMultiple(boneName) {
|
|
94
|
+
return bones_state.structure[boneName] && bones_state.structure[boneName]["multiple"]
|
|
95
|
+
? !!bones_state.structure[boneName]["multiple"]
|
|
96
|
+
: false
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function langPrefix(lang, value) {
|
|
100
|
+
if (showflags) {
|
|
101
|
+
const entry = languageMap.find(({ lang: l }) => l === lang)
|
|
102
|
+
if (entry) {
|
|
103
|
+
value = `${entry.flag} ${value}`
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return value
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function renderSingleValue(boneName, options, value = null, skel = null, lang = null) {
|
|
110
|
+
let boneStructure = bones_state.structure[boneName]
|
|
111
|
+
if (boneStructure == null) {
|
|
112
|
+
return "-"
|
|
113
|
+
}
|
|
114
|
+
if (!boneStructure["multiple"]) {
|
|
115
|
+
if (skel === null) {
|
|
116
|
+
skel = bones_state.skel
|
|
117
|
+
}
|
|
118
|
+
value = skel[boneName]
|
|
119
|
+
if (lang) {
|
|
120
|
+
value = skel[boneName][lang]
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (value === "" || value === null || value === undefined || !boneStructure) {
|
|
125
|
+
return "-"
|
|
126
|
+
} else if (boneStructure["type"] === "select" || boneStructure["type"].startsWith("select.")) {
|
|
127
|
+
// extract description from tuple
|
|
128
|
+
if (boneStructure["values"].length > 0) {
|
|
129
|
+
let returnValue = boneStructure["values"]?.filter((x) => x[0].toString() === value.toString())?.[0]?.[1]
|
|
130
|
+
return returnValue ? returnValue : "-"
|
|
131
|
+
}
|
|
132
|
+
if (Object.keys(boneStructure["values"]).length > 0) {
|
|
133
|
+
let returnValue = Object.entries(boneStructure["values"])?.filter(
|
|
134
|
+
(x) => x[0].toString() === value.toString()
|
|
135
|
+
)?.[0]?.[1]
|
|
136
|
+
return returnValue ? returnValue : "-"
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return "-"
|
|
140
|
+
} else if (boneStructure["type"] === "date" || boneStructure["type"].startsWith("date.")) {
|
|
141
|
+
if (options && options === "time") {
|
|
142
|
+
return new Date(value).toLocaleTimeString()
|
|
143
|
+
} else if (options && options === "date") {
|
|
144
|
+
return new Date(value).toLocaleDateString()
|
|
145
|
+
}
|
|
146
|
+
return new Date(value).toLocaleString()
|
|
147
|
+
} else if (boneStructure["type"] === "relational" || boneStructure["type"].startsWith("relational.")) {
|
|
148
|
+
return Utils.formatString(boneStructure["format"], { ...value, lang: lang })
|
|
149
|
+
} else if (boneStructure["type"] === "hierarchy" || boneStructure["type"].startsWith("hierarchy.")) {
|
|
150
|
+
return Utils.formatString(boneStructure["format"], { ...value, lang: lang })
|
|
151
|
+
} else if (boneStructure["type"] === "record" || boneStructure["type"].startsWith("record.")) {
|
|
152
|
+
if (boneStructure["format"]?.includes("$(dest.")) {
|
|
153
|
+
return Utils.formatString(boneStructure["format"], { dest: value, lang: lang })
|
|
154
|
+
}
|
|
155
|
+
return Utils.formatString(boneStructure["format"], { ...value, lang: lang })
|
|
156
|
+
} else if (boneStructure["type"] === "bool") {
|
|
157
|
+
if (typeof t === "function") {
|
|
158
|
+
return value ? t("bones.bool.true") : t("bones.bool.false")
|
|
159
|
+
}
|
|
160
|
+
return value ? "Ja" : "Nein"
|
|
161
|
+
} else if (boneStructure["type"] === "raw.json") {
|
|
162
|
+
return JSON.stringify(value)
|
|
163
|
+
} else {
|
|
164
|
+
value = Utils.unescape(value)
|
|
165
|
+
return value.toString()
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function renderMultipleValue(boneName, options, skel = null, lang = null) {
|
|
170
|
+
if (skel === null) {
|
|
171
|
+
skel = bones_state.skel
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
let value = skel[boneName]
|
|
175
|
+
|
|
176
|
+
if (lang) {
|
|
177
|
+
value = skel[boneName][lang]
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (value && value.length > 0) {
|
|
181
|
+
return value
|
|
182
|
+
.map((x) => {
|
|
183
|
+
if (selectedLang) {
|
|
184
|
+
if (selectedLang === lang) {
|
|
185
|
+
return renderSingleValue(boneName, options, x, skel, lang)
|
|
186
|
+
}
|
|
187
|
+
} else {
|
|
188
|
+
return renderSingleValue(boneName, options, x, skel, lang)
|
|
189
|
+
}
|
|
190
|
+
})
|
|
191
|
+
.join(", ")
|
|
192
|
+
}
|
|
193
|
+
return "-"
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return {
|
|
197
|
+
getBoneValue,
|
|
198
|
+
bones_state,
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export default boneLogic
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<wa-switch
|
|
3
|
+
class="bone-widget bone-widget-boolean bone-widget-boolean-default"
|
|
4
|
+
:class="[`bone-widget-boolean-${name}`]"
|
|
5
|
+
:disabled="boneState.readonly"
|
|
6
|
+
:checked="state.value"
|
|
7
|
+
:data-user-invalid="boneState.errorMessages.length === 0 ? undefined : true"
|
|
8
|
+
@change="changeEvent"
|
|
9
|
+
></wa-switch>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script setup>
|
|
13
|
+
import { reactive, onMounted, inject, computed } from "vue"
|
|
14
|
+
/**
|
|
15
|
+
* Schalter für boolesche Werte (true/false).
|
|
16
|
+
*
|
|
17
|
+
* Verfügbar in drei Varianten: `bool` (Switch), `bool.choose` (Ja/Nein-Buttons),
|
|
18
|
+
* `bool.select` (Dropdown). Der Wert `null`, `undefined`, `false` und `""` wird
|
|
19
|
+
* einheitlich als `false` behandelt.
|
|
20
|
+
*
|
|
21
|
+
* @displayName BooleanBone
|
|
22
|
+
*
|
|
23
|
+
* @cssClass bone-widget - Basis-Klasse aller Bone-Widgets
|
|
24
|
+
* @cssClass bone-widget-boolean - Kennzeichnet den Bone-Typ
|
|
25
|
+
* @cssClass bone-widget-boolean-default - Standard-Variante
|
|
26
|
+
* @cssClass bone-widget-boolean-{name} - Dynamisch gesetzt auf den Bone-Namen
|
|
27
|
+
*/
|
|
28
|
+
defineOptions({
|
|
29
|
+
inheritAttrs: false,
|
|
30
|
+
})
|
|
31
|
+
const props = defineProps({
|
|
32
|
+
/** Bone-Name – wird in jedem `change`-Event als erstes Argument übergeben. */
|
|
33
|
+
name: String,
|
|
34
|
+
/** Aktueller Bone-Wert. `null`, `undefined`, `false` und `""` gelten als `false`. */
|
|
35
|
+
value: [Object, String, Number, Boolean, Array],
|
|
36
|
+
/** Index im Multiple-Array; `undefined` bei Einzelwert. */
|
|
37
|
+
index: Number,
|
|
38
|
+
/** Sprach-Key bei mehrsprachigen Bones, z.B. `"de"`. */
|
|
39
|
+
lang: String,
|
|
40
|
+
/** Bone-Struktur (aktuell nicht aktiv genutzt). */
|
|
41
|
+
bone: Object,
|
|
42
|
+
/** Autofocus (aktuell nicht aktiv genutzt). */
|
|
43
|
+
autofocus: Boolean,
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const emit = defineEmits([
|
|
47
|
+
/**
|
|
48
|
+
* Wird bei jeder Wertänderung sowie beim Mount (Initialisierung) gefeuert.
|
|
49
|
+
* @arg {string} name - Bone-Name
|
|
50
|
+
* @arg {boolean} value - Aktueller Wert
|
|
51
|
+
* @arg {string|undefined} lang - Sprach-Key
|
|
52
|
+
* @arg {number|undefined} index - Index im Multiple-Array
|
|
53
|
+
*/
|
|
54
|
+
"change",
|
|
55
|
+
])
|
|
56
|
+
const boneState = inject("boneState")
|
|
57
|
+
const state = reactive({
|
|
58
|
+
value: computed(() => {
|
|
59
|
+
return ![false, null, undefined, ""].includes(props.value)
|
|
60
|
+
}),
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
function changeEvent(event) {
|
|
64
|
+
emit("change", props.name, event.target.checked, props.lang, props.index)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
onMounted(() => {
|
|
68
|
+
let val = props.value
|
|
69
|
+
if (!val) {
|
|
70
|
+
val = false
|
|
71
|
+
}
|
|
72
|
+
emit("change", props.name, val, props.lang, props.index) //init
|
|
73
|
+
})
|
|
74
|
+
</script>
|
|
75
|
+
|
|
76
|
+
<style scoped>
|
|
77
|
+
wa-switch {
|
|
78
|
+
padding: calc(var(--wa-form-control-height) / 2 - var(--wa-form-control-toggle-size) / 2 - 1px);
|
|
79
|
+
border: 1px solid var(--wa-color-border-quiet);
|
|
80
|
+
border-radius: var(--wa-border-radius-m);
|
|
81
|
+
background-color: var(--wa-color-neutral-on-loud);
|
|
82
|
+
}
|
|
83
|
+
</style>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- readonly an der Gruppe: wa-radio-group markiert nur Radios, die selbst
|
|
3
|
+
nicht disabled sind — sonst wäre bei readonly keine Auswahl sichtbar -->
|
|
4
|
+
<wa-radio-group
|
|
5
|
+
:value="state.value"
|
|
6
|
+
:disabled="boneState.readonly"
|
|
7
|
+
class="bone-widget bone-widget-boolean bone-widget-boolean-choose"
|
|
8
|
+
:class="[`bone-widget-boolean-${name}`]"
|
|
9
|
+
:required="
|
|
10
|
+
boneState.bonestructure.required && !boneState.bonestructure.multiple && !boneState.bonestructure.languages
|
|
11
|
+
"
|
|
12
|
+
:data-user-invalid="boneState.errorMessages.length === 0 ? undefined : true"
|
|
13
|
+
@change="changeEvent"
|
|
14
|
+
>
|
|
15
|
+
<wa-radio :value="'true'">
|
|
16
|
+
{{ $t("bones.bool.true") }}
|
|
17
|
+
</wa-radio>
|
|
18
|
+
<wa-radio :value="'false'">
|
|
19
|
+
{{ $t("bones.bool.false") }}
|
|
20
|
+
</wa-radio>
|
|
21
|
+
</wa-radio-group>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<script setup>
|
|
25
|
+
import { reactive, onMounted, inject, computed } from "vue"
|
|
26
|
+
defineOptions({
|
|
27
|
+
inheritAttrs: false,
|
|
28
|
+
})
|
|
29
|
+
const props = defineProps({
|
|
30
|
+
name: String,
|
|
31
|
+
value: [Object, String, Number, Boolean, Array],
|
|
32
|
+
index: Number,
|
|
33
|
+
lang: String,
|
|
34
|
+
bone: Object,
|
|
35
|
+
autofocus: Boolean,
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
const emit = defineEmits(["change"])
|
|
39
|
+
const boneState = inject("boneState")
|
|
40
|
+
const state = reactive({
|
|
41
|
+
value: computed(() => {
|
|
42
|
+
return "" + ![false, null, undefined, "", "false"].includes(props.value)
|
|
43
|
+
}),
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
function changeEvent(event) {
|
|
47
|
+
emit("change", props.name, event.target.value, props.lang, props.index)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
onMounted(() => {
|
|
51
|
+
let val = props.value
|
|
52
|
+
if (!val) {
|
|
53
|
+
val = false
|
|
54
|
+
}
|
|
55
|
+
emit("change", props.name, val, props.lang, props.index) //init
|
|
56
|
+
})
|
|
57
|
+
</script>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<wa-select
|
|
3
|
+
:disabled="boneState.readonly"
|
|
4
|
+
:value="state.value"
|
|
5
|
+
max-options-visible="0"
|
|
6
|
+
class="bone-widget bone-widget-boolean bone-widget-boolean-select"
|
|
7
|
+
:class="[`bone-widget-boolean-${name}`]"
|
|
8
|
+
:data-user-invalid="boneState.errorMessages.length === 0 ? undefined : true"
|
|
9
|
+
@change="changeEvent"
|
|
10
|
+
>
|
|
11
|
+
<!-- String-Werte: wa-select gleicht seinen Wert beim Setzen mit den
|
|
12
|
+
Options-Werten ab; boolesche werden erst später zu Strings, der
|
|
13
|
+
gespeicherte Wert erschiene dann nicht -->
|
|
14
|
+
<wa-option
|
|
15
|
+
v-for="val in ['true', 'false']"
|
|
16
|
+
:key="val"
|
|
17
|
+
:value="val"
|
|
18
|
+
>
|
|
19
|
+
{{ $t(`bones.bool.${val}`) }}
|
|
20
|
+
</wa-option>
|
|
21
|
+
</wa-select>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<script setup>
|
|
25
|
+
import { reactive, onMounted, inject, computed } from "vue"
|
|
26
|
+
defineOptions({
|
|
27
|
+
inheritAttrs: false,
|
|
28
|
+
})
|
|
29
|
+
const props = defineProps({
|
|
30
|
+
name: String,
|
|
31
|
+
value: [Object, String, Number, Boolean, Array],
|
|
32
|
+
index: Number,
|
|
33
|
+
lang: String,
|
|
34
|
+
bone: Object,
|
|
35
|
+
autofocus: Boolean,
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
const emit = defineEmits(["change"])
|
|
39
|
+
|
|
40
|
+
const boneState = inject("boneState")
|
|
41
|
+
const state = reactive({
|
|
42
|
+
value: computed(() => {
|
|
43
|
+
return "" + ![false, null, undefined, "", "false"].includes(props.value)
|
|
44
|
+
}),
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
function changeEvent(event) {
|
|
48
|
+
emit("change", props.name, event.target.value, props.lang, props.index)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
onMounted(() => {
|
|
52
|
+
let val = props.value
|
|
53
|
+
if (!val) {
|
|
54
|
+
val = false
|
|
55
|
+
}
|
|
56
|
+
emit("change", props.name, val, props.lang, props.index) //init
|
|
57
|
+
})
|
|
58
|
+
</script>
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="bone-widget-wrapper bone-widget bone-widget-raw bone-widget-raw-default"
|
|
4
|
+
:class="{ 'is-max-size': state.max }"
|
|
5
|
+
>
|
|
6
|
+
<textarea
|
|
7
|
+
ref="element"
|
|
8
|
+
:disabled="boneState?.readonly"
|
|
9
|
+
:placeholder="state.placeholder"
|
|
10
|
+
:data-user-invalid="boneState.errorMessages.length === 0 ? undefined : true"
|
|
11
|
+
></textarea>
|
|
12
|
+
<wa-button
|
|
13
|
+
appearance="plain"
|
|
14
|
+
class="bone-expand-button"
|
|
15
|
+
@click="state.max = !state.max"
|
|
16
|
+
>
|
|
17
|
+
<wa-icon :name="state.max ? 'compress' : 'expand'"></wa-icon>
|
|
18
|
+
</wa-button>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<input
|
|
22
|
+
type="text"
|
|
23
|
+
class="bone-widget-raw-hidden"
|
|
24
|
+
:value="state.value"
|
|
25
|
+
:required="
|
|
26
|
+
boneState.bonestructure.required && !boneState.bonestructure.multiple && !boneState.bonestructure.languages
|
|
27
|
+
"
|
|
28
|
+
/>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<script setup>
|
|
32
|
+
import { reactive, onMounted, inject, computed, ref } from "vue"
|
|
33
|
+
import { basicSetup } from "codemirror"
|
|
34
|
+
import { EditorView, keymap, drawSelection } from "@codemirror/view"
|
|
35
|
+
import { syntaxHighlighting, defaultHighlightStyle, LanguageDescription } from "@codemirror/language"
|
|
36
|
+
import { indentLess, indentMore, indentWithTab, indentSelection, insertTab } from "@codemirror/commands"
|
|
37
|
+
import { indentString, indentUnit } from "@codemirror/language"
|
|
38
|
+
import { EditorState } from "@codemirror/state"
|
|
39
|
+
import { languages } from "@codemirror/language-data"
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Code-Editor auf Basis von CodeMirror für syntaxhervorgehobene Quelltext-Eingabe.
|
|
43
|
+
*
|
|
44
|
+
* Erkennt die Programmiersprache anhand von `boneState.bonestructure.type`
|
|
45
|
+
* (z.B. `raw.code.python`, `raw.code.html`, `raw.code.javascript`) und lädt
|
|
46
|
+
* das passende CodeMirror-Language-Plugin dynamisch nach. Unterstützt
|
|
47
|
+
* Mehrfachwerte (`multiple`). Ein Expand-Button ermöglicht das Aufklappen
|
|
48
|
+
* auf volle Höhe.
|
|
49
|
+
*
|
|
50
|
+
* @displayName CodeBone
|
|
51
|
+
*
|
|
52
|
+
* @cssClass bone-widget - Basis-Klasse aller Bone-Widgets
|
|
53
|
+
* @cssClass bone-widget-raw - Kennzeichnet den übergeordneten Bone-Typ
|
|
54
|
+
* @cssClass bone-widget-raw-default - Standard-Variante
|
|
55
|
+
* @cssClass bone-widget-wrapper - Umschließt Editor und Expand-Button
|
|
56
|
+
* @cssClass is-max-size - Wird per Expand-Button umgeschaltet; hebt die maximale Höhe auf
|
|
57
|
+
*/
|
|
58
|
+
defineOptions({
|
|
59
|
+
inheritAttrs: false,
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
const element = ref(null)
|
|
63
|
+
const view = ref(null)
|
|
64
|
+
|
|
65
|
+
const props = defineProps({
|
|
66
|
+
/** Bone-Name – wird in jedem `change`-Event als erstes Argument übergeben. */
|
|
67
|
+
name: String,
|
|
68
|
+
/** Aktueller Bone-Wert (Quelltext als String). */
|
|
69
|
+
value: [Object, String, Number, Boolean, Array],
|
|
70
|
+
/** Index im Multiple-Array; `undefined` bei Einzelwert. */
|
|
71
|
+
index: Number,
|
|
72
|
+
/** Sprach-Key bei mehrsprachigen Bones (CodeBone unterstützt kein multilang). */
|
|
73
|
+
lang: String,
|
|
74
|
+
/** Bone-Struktur (aktuell nicht aktiv genutzt). */
|
|
75
|
+
bone: Object,
|
|
76
|
+
/** Setzt den Fokus nach dem Mount auf den CodeMirror-Editor. */
|
|
77
|
+
autofocus: Boolean,
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
const emit = defineEmits([
|
|
81
|
+
/**
|
|
82
|
+
* Wird bei jeder Wertänderung sowie beim Mount (Initialisierung) gefeuert.
|
|
83
|
+
* @arg {string} name - Bone-Name
|
|
84
|
+
* @arg {string} value - Aktueller Quelltext
|
|
85
|
+
* @arg {string|undefined} lang - Sprach-Key
|
|
86
|
+
* @arg {number|undefined} index - Index im Multiple-Array
|
|
87
|
+
*/
|
|
88
|
+
"change",
|
|
89
|
+
])
|
|
90
|
+
|
|
91
|
+
const boneState = inject("boneState")
|
|
92
|
+
const state = reactive({
|
|
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
|
+
value: "",
|
|
102
|
+
max: false,
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
function editorFromTextArea(textarea, extensions) {
|
|
106
|
+
let _view = new EditorView({ doc: textarea.value, extensions })
|
|
107
|
+
|
|
108
|
+
textarea.parentNode.insertBefore(_view.dom, textarea)
|
|
109
|
+
textarea.style.display = "none"
|
|
110
|
+
|
|
111
|
+
if (textarea.form) {
|
|
112
|
+
textarea.form.addEventListener("submit", () => {
|
|
113
|
+
textarea.value = _view.state.doc.toString()
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
indentString(_view.state, 4)
|
|
118
|
+
|
|
119
|
+
let listener = () => {
|
|
120
|
+
let lines = ""
|
|
121
|
+
for (let i = 0; i < _view.state.doc.lines; ++i) {
|
|
122
|
+
let line = _view.state.doc.line(i + 1).text
|
|
123
|
+
lines += line + "\n"
|
|
124
|
+
}
|
|
125
|
+
state.value = lines
|
|
126
|
+
emit("change", props.name, state.value, props.lang, props.index)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
_view.dom.addEventListener("input", listener)
|
|
130
|
+
_view.dom.addEventListener("keyup", listener)
|
|
131
|
+
_view.dom.addEventListener("paste", listener)
|
|
132
|
+
_view.dom.addEventListener("cut", listener)
|
|
133
|
+
return _view
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async function build() {
|
|
137
|
+
const exts = [
|
|
138
|
+
basicSetup,
|
|
139
|
+
syntaxHighlighting(defaultHighlightStyle),
|
|
140
|
+
keymap.of([indentWithTab]),
|
|
141
|
+
indentUnit.of(" "),
|
|
142
|
+
EditorState.tabSize.of(4),
|
|
143
|
+
EditorView.lineWrapping,
|
|
144
|
+
drawSelection(),
|
|
145
|
+
]
|
|
146
|
+
|
|
147
|
+
let langDesc = LanguageDescription.matchLanguageName(
|
|
148
|
+
languages,
|
|
149
|
+
boneState?.bonestructure?.type.replace("raw.code.", "")
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
if (langDesc) {
|
|
153
|
+
const support = await langDesc.load()
|
|
154
|
+
exts.push(support)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (boneState?.readonly) {
|
|
158
|
+
exts.push(EditorView.editable.of(false))
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return exts
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
onMounted(async () => {
|
|
165
|
+
if (props.value !== null) {
|
|
166
|
+
state.value = props.value
|
|
167
|
+
}
|
|
168
|
+
const exts = await build()
|
|
169
|
+
view.value = editorFromTextArea(element.value, exts)
|
|
170
|
+
|
|
171
|
+
//init editor
|
|
172
|
+
view.value.dispatch({
|
|
173
|
+
changes: { from: 0, to: view.value.state.doc.length, insert: state.value },
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
emit("change", props.name, props.value, props.lang, props.index) //init
|
|
177
|
+
})
|
|
178
|
+
</script>
|
|
179
|
+
<style scoped>
|
|
180
|
+
.bone-widget-raw-hidden {
|
|
181
|
+
max-height: 0;
|
|
182
|
+
display: block;
|
|
183
|
+
visibility: hidden;
|
|
184
|
+
width: 100%;
|
|
185
|
+
pointer-events: none;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.bone-expand-button {
|
|
189
|
+
position: absolute;
|
|
190
|
+
bottom: 0px;
|
|
191
|
+
right: 10px;
|
|
192
|
+
z-index: 1;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.bone-widget-wrapper {
|
|
196
|
+
position: relative;
|
|
197
|
+
display: flex;
|
|
198
|
+
height: 100%;
|
|
199
|
+
width: 100%;
|
|
200
|
+
}
|
|
201
|
+
:deep(.cm-editor) {
|
|
202
|
+
width: 100%;
|
|
203
|
+
|
|
204
|
+
& .cm-scroller {
|
|
205
|
+
min-height: 3em;
|
|
206
|
+
max-height: 28em;
|
|
207
|
+
overflow-y: auto;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.bone-widget-wrapper.is-max-size :deep(.cm-editor) .cm-scroller {
|
|
212
|
+
max-height: none;
|
|
213
|
+
}
|
|
214
|
+
</style>
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="wa-flank wa-align-item-center">
|
|
3
|
+
<wa-color-picker
|
|
4
|
+
class="bone-widget bone-widget-color bone-widget-color-default"
|
|
5
|
+
:class="[`bone-widget-color-${name}`]"
|
|
6
|
+
:disabled="boneState.readonly"
|
|
7
|
+
:value="value"
|
|
8
|
+
:required="
|
|
9
|
+
boneState.bonestructure.required && !boneState.bonestructure.multiple && !boneState.bonestructure.languages
|
|
10
|
+
"
|
|
11
|
+
:data-user-invalid="boneState.errorMessages.length === 0 ? undefined : true"
|
|
12
|
+
@change="changeEvent"
|
|
13
|
+
></wa-color-picker>
|
|
14
|
+
<span>{{ value || "-" }}</span>
|
|
15
|
+
<wa-copy-button
|
|
16
|
+
:disabled="!value"
|
|
17
|
+
:value="value"
|
|
18
|
+
></wa-copy-button>
|
|
19
|
+
</div>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<script setup>
|
|
23
|
+
import { reactive, onMounted, inject } from "vue"
|
|
24
|
+
/**
|
|
25
|
+
* Farbauswahl-Feld über ein natives `<wa-color-picker>`-Element.
|
|
26
|
+
*
|
|
27
|
+
* Speichert den gewählten Farbwert als Hex-String, z.B. `"#e74c3c"`.
|
|
28
|
+
* Unterstützt mehrfache Werte (`multiple`), aber keine Mehrsprachigkeit.
|
|
29
|
+
*
|
|
30
|
+
* @displayName ColorBone
|
|
31
|
+
*
|
|
32
|
+
* @cssClass bone-widget - Basis-Klasse aller Bone-Widgets
|
|
33
|
+
* @cssClass bone-widget-color - Kennzeichnet den Bone-Typ
|
|
34
|
+
* @cssClass bone-widget-color-default - Standard-Variante
|
|
35
|
+
* @cssClass bone-widget-color-{name} - Dynamisch gesetzt auf den Bone-Namen, z.B. `bone-widget-color-color`
|
|
36
|
+
*/
|
|
37
|
+
defineOptions({
|
|
38
|
+
inheritAttrs: false,
|
|
39
|
+
})
|
|
40
|
+
const props = defineProps({
|
|
41
|
+
/** Bone-Name – wird in jedem `change`-Event als erstes Argument übergeben. */
|
|
42
|
+
name: String,
|
|
43
|
+
/** Aktueller Bone-Wert als Hex-String, z.B. `"#e74c3c"`, oder `null`. */
|
|
44
|
+
value: [Object, String, Number, Boolean, Array],
|
|
45
|
+
/** Index im Multiple-Array; `undefined` bei Einzelwert. */
|
|
46
|
+
index: Number,
|
|
47
|
+
/** Sprach-Key bei mehrsprachigen Bones, z.B. `"de"`. */
|
|
48
|
+
lang: String,
|
|
49
|
+
/** Bone-Struktur (aktuell nicht aktiv genutzt). */
|
|
50
|
+
bone: Object,
|
|
51
|
+
/** Setzt den Fokus nach 600 ms auf das Input-Element. */
|
|
52
|
+
autofocus: Boolean,
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const emit = defineEmits([
|
|
56
|
+
/**
|
|
57
|
+
* Wird bei jeder Wertänderung sowie beim Mount (Initialisierung) gefeuert.
|
|
58
|
+
* @arg {string} name - Bone-Name
|
|
59
|
+
* @arg {string|null} value - Gewählter Farbwert als Hex-String oder `null`
|
|
60
|
+
* @arg {string|undefined} lang - Sprach-Key
|
|
61
|
+
* @arg {number|undefined} index - Index im Multiple-Array
|
|
62
|
+
*/
|
|
63
|
+
"change",
|
|
64
|
+
])
|
|
65
|
+
const boneState = inject("boneState")
|
|
66
|
+
const state = reactive({})
|
|
67
|
+
|
|
68
|
+
function changeEvent(event) {
|
|
69
|
+
emit("change", props.name, event.target.value, props.lang, props.index)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
onMounted(() => {
|
|
73
|
+
emit("change", props.name, props.value, props.lang, props.index) //init
|
|
74
|
+
})
|
|
75
|
+
</script>
|