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,201 @@
1
+ <template>
2
+ <div class="image-description-wrapper">
3
+ <div class="image-description-grid">
4
+ <div>
5
+ <vi-image
6
+ :src="state.url"
7
+ style="height: 50px"
8
+ ></vi-image>
9
+ </div>
10
+
11
+ <div class="image-description-flex">
12
+ <wa-tab-group
13
+ v-if="state.value"
14
+ class="bone-lang-tabs"
15
+ placement="bottom"
16
+ >
17
+ <template
18
+ v-for="(_val, lang) in state.value"
19
+ :key="lang + '_tab'"
20
+ >
21
+ <wa-tab
22
+ slot="nav"
23
+ :panel="'lang_' + lang"
24
+ :disabled="state.loading"
25
+ @click="state.currentLang = lang"
26
+ >
27
+ {{ $t(lang) }}
28
+ </wa-tab>
29
+
30
+ <wa-tab-panel :name="'lang_' + lang">
31
+ <wa-textarea
32
+ :value="state.value[lang]"
33
+ :label="t('actions.describeImage.label', { lang })"
34
+ @change="updateValue($event, lang)"
35
+ ></wa-textarea>
36
+ </wa-tab-panel>
37
+ </template>
38
+ </wa-tab-group>
39
+
40
+ <wa-input
41
+ v-model="state.prompt"
42
+ :placeholder="t('actions.describeImage.instructions')"
43
+ ></wa-input>
44
+ <span class="image-description-small-print">
45
+ {{ t("actions.aiHint") }}
46
+ </span>
47
+ <wa-button
48
+ size="small"
49
+ variant="brand"
50
+ :loading="state.loading"
51
+ @click="describe"
52
+ >
53
+ {{ t("actions.describeImage.run") }}
54
+ </wa-button>
55
+ </div>
56
+ </div>
57
+ </div>
58
+
59
+ <div
60
+ slot="footer"
61
+ class="footer"
62
+ >
63
+ <wa-button
64
+ variant="danger"
65
+ size="small"
66
+ appearance="outlined"
67
+ @click="CloseAction"
68
+ >
69
+ {{ $t("relation.abort") }}
70
+ </wa-button>
71
+
72
+ <wa-button
73
+ variant="success"
74
+ size="small"
75
+ @click="ApplySelection"
76
+ >
77
+ {{ t("actions.describeImage.apply") }}
78
+ </wa-button>
79
+ </div>
80
+ </template>
81
+
82
+ <script setup>
83
+ import { useI18n } from "vue-i18n"
84
+ import { reactive, onMounted, inject, computed } from "vue"
85
+ import { createControllerFetch } from "../../../request/index.js"
86
+ import viImage from "@viur/vue-utils/generic/Image.vue"
87
+
88
+ const { t } = useI18n()
89
+
90
+ const props = defineProps({
91
+ name: String,
92
+ module: String,
93
+ tabId: String,
94
+ action: Object,
95
+ params: Object,
96
+ })
97
+ const viform = inject("viform")
98
+ const emit = defineEmits(["close", "next"])
99
+ const describeImageFetch = createControllerFetch({ endpoint: "describe_image", method: "POST" })
100
+
101
+ const state = reactive({
102
+ value: null,
103
+ currentLang: null,
104
+ url: computed(
105
+ () => (import.meta.env.VITE_API_URL ?? window.location.origin) + (props.params.value?.dest?.downloadUrl ?? "")
106
+ ),
107
+ prompt: null,
108
+ loading: false,
109
+ })
110
+
111
+ async function describe() {
112
+ state.loading = true
113
+ try {
114
+ const fetchResult = describeImageFetch(
115
+ "assistant",
116
+ "/",
117
+ {
118
+ filekey: props.params.value.dest.key,
119
+ context: JSON.stringify(viform?.value?.state?.skel),
120
+ prompt: state.prompt,
121
+ language: state.currentLang,
122
+ },
123
+ { immediate: false }
124
+ )
125
+ await fetchResult.execute()
126
+ // v2 envelope carries the payload in `data`; fall back to the raw body for
127
+ // non-envelope responses.
128
+ const result = fetchResult.data.value
129
+ state.value[state.currentLang] = result?.data ?? result
130
+ } finally {
131
+ state.loading = false
132
+ }
133
+ }
134
+
135
+ onMounted(() => {
136
+ state.value = props.params.value?.rel?.alt
137
+ if (!state.value) {
138
+ const langs = {}
139
+ for (const l of props.params.bone?.using?.alt?.languages ?? []) {
140
+ langs[l] = ""
141
+ }
142
+ state.value = langs
143
+ }
144
+ state.currentLang = props.params.bone?.using?.alt?.languages?.[0]
145
+ })
146
+
147
+ function updateValue(e, lang) {
148
+ state.value[lang] = e.target.value
149
+ }
150
+
151
+ function CloseAction() {
152
+ emit("close")
153
+ }
154
+
155
+ function ApplySelection() {
156
+ const val = { ...(props.params.value ?? {}) }
157
+ if (!val.rel) {
158
+ val.rel = { alt: state.value }
159
+ } else {
160
+ val.rel = { ...val.rel, alt: state.value }
161
+ }
162
+ emit("close", val, props.params.lang ?? null)
163
+ }
164
+ </script>
165
+
166
+ <style scoped>
167
+ .image-description-wrapper {
168
+ padding: var(--wa-space-l);
169
+ display: flex;
170
+ flex-direction: column;
171
+ gap: var(--wa-space-s);
172
+ }
173
+
174
+ .image-description-grid {
175
+ display: grid;
176
+ grid-template-columns: 15em minmax(0, 1fr);
177
+ gap: var(--wa-space-l);
178
+ }
179
+
180
+ .footer {
181
+ display: flex;
182
+ justify-content: space-between;
183
+ }
184
+
185
+ .image-description-small-print {
186
+ font-size: 0.7em;
187
+ }
188
+
189
+ .image-description-flex {
190
+ display: flex;
191
+ flex-direction: column;
192
+ gap: var(--wa-space-s);
193
+ }
194
+
195
+ wa-textarea {
196
+ &::part(form-control-label) {
197
+ margin-bottom: var(--wa-space-xs);
198
+ font-weight: 600;
199
+ }
200
+ }
201
+ </style>
@@ -0,0 +1,27 @@
1
+ <script>
2
+ import { downloadUrlFor } from "../../../request/index.js"
3
+
4
+ /**
5
+ * Direct-fire Action: lädt die im Bone-Value referenzierte Datei herunter.
6
+ * Wird von `BoneActions` bei `type: "callback"` direkt aufgerufen — kein Dialog.
7
+ *
8
+ * @param {{ value: object, name: string, lang: string, index: number, bone: object, boneState: object }} ctx
9
+ */
10
+ export function handler(ctx) {
11
+ const url = downloadUrlFor(ctx.value)
12
+ if (!url) return
13
+
14
+ // Anchor-Click statt window.open: funktioniert auch mit Data-URLs
15
+ // (Browser blockt Top-Level-Navigation zu data:-URLs aus Phishing-Gründen).
16
+ const a = document.createElement("a")
17
+ a.href = url
18
+ a.download = ctx.value?.dest?.name ?? ""
19
+ a.rel = "noopener"
20
+ a.target = "_blank"
21
+ document.body.appendChild(a)
22
+ a.click()
23
+ a.remove()
24
+ }
25
+
26
+ export default {}
27
+ </script>
@@ -0,0 +1,14 @@
1
+ <script>
2
+ /**
3
+ * Platzhalter-Action zum Testen der Anzeige mehrerer Buttons.
4
+ * TODO: wieder entfernen sobald nicht mehr benötigt.
5
+ *
6
+ * @param {{ value: object, name: string, lang: string, index: number, bone: object, boneState: object }} ctx
7
+ */
8
+ export function handler(ctx) {
9
+ // eslint-disable-next-line no-console
10
+ console.log("[Placeholder Action]", ctx)
11
+ }
12
+
13
+ export default {}
14
+ </script>
@@ -0,0 +1,238 @@
1
+ <template>
2
+ <div class="translate-wrapper">
3
+ <div class="translate-grid">
4
+ <div class="translate-flex">
5
+ <wa-textarea
6
+ :value="state.value_de"
7
+ :label="t('actions.translate.original', { lang: 'de' })"
8
+ @change="updateValueDe"
9
+ ></wa-textarea>
10
+ </div>
11
+
12
+ <div class="translate-icon-wrap">
13
+ <wa-icon name="arrows-left-right"></wa-icon>
14
+ </div>
15
+
16
+ <div class="translate-flex">
17
+ <wa-textarea
18
+ :value="state.result || '-'"
19
+ :label="t('actions.translate.target', { lang: state.currentLang })"
20
+ @change="updateValue"
21
+ ></wa-textarea>
22
+ </div>
23
+ </div>
24
+
25
+ <div class="translate-footer">
26
+ <span class="translate-small-print">
27
+ {{ t("actions.aiHint") }}
28
+ </span>
29
+ <div></div>
30
+ <wa-button
31
+ size="small"
32
+ variant="brand"
33
+ :loading="state.loading"
34
+ @click="translate"
35
+ >
36
+ {{ t("actions.translate.run") }}
37
+ </wa-button>
38
+ </div>
39
+ </div>
40
+
41
+ <div
42
+ slot="footer"
43
+ class="translate-dialog-footer"
44
+ >
45
+ <wa-button
46
+ variant="danger"
47
+ size="small"
48
+ appearance="outlined"
49
+ @click="CloseAction"
50
+ >
51
+ {{ $t("relation.abort") }}
52
+ </wa-button>
53
+
54
+ <div class="translate-dialog-footer-spacer"></div>
55
+
56
+ <wa-button
57
+ variant="success"
58
+ appearance="outlined"
59
+ size="small"
60
+ :disabled="!state.nextlang"
61
+ @click="nextlang"
62
+ >
63
+ {{ t("actions.translate.applyNext") }}
64
+ </wa-button>
65
+ <wa-button
66
+ variant="success"
67
+ size="small"
68
+ @click="ApplySelection"
69
+ >
70
+ {{ t("actions.translate.apply", { lang: state.currentLang }) }}
71
+ </wa-button>
72
+ </div>
73
+ </template>
74
+
75
+ <script setup>
76
+ import { useI18n } from "vue-i18n"
77
+ import { reactive, onMounted, computed, watch } from "vue"
78
+ import { createControllerFetch } from "../../../request/index.js"
79
+
80
+ const { t } = useI18n()
81
+
82
+ const props = defineProps({
83
+ name: String,
84
+ module: String,
85
+ tabId: String,
86
+ action: Object,
87
+ params: Object,
88
+ })
89
+
90
+ const emit = defineEmits(["close", "next"])
91
+ const translateFetch = createControllerFetch({ endpoint: "translate", method: "POST" })
92
+
93
+ const state = reactive({
94
+ result: null,
95
+ currentLang: null,
96
+ rawLang: computed(() => state.currentLang?.split("_")[0]),
97
+ simple: computed(() => state.currentLang?.split("-x-")?.length === 2),
98
+ value_de: null,
99
+ loading: false,
100
+ nextlang: computed(() => {
101
+ const val = getValue()
102
+ if (!val) return "de"
103
+ for (const [l, v] of Object.entries(val)) {
104
+ if ((!v || (Array.isArray(v) && (v.length === 0 || !v?.[props.params.index]))) && state.currentLang !== l) {
105
+ return l
106
+ }
107
+ }
108
+ return Object.keys(val).filter((x) => x !== "de")?.[0]
109
+ }),
110
+ })
111
+
112
+ async function translate() {
113
+ state.loading = true
114
+ try {
115
+ const fetchResult = translateFetch(
116
+ "assistant",
117
+ "/",
118
+ {
119
+ text: state.value_de,
120
+ language: state.rawLang,
121
+ characteristic: state.simple ? "simple" : null,
122
+ },
123
+ { immediate: false }
124
+ )
125
+ await fetchResult.execute()
126
+ // v2 envelope carries the payload in `data`; fall back to the raw body for
127
+ // non-envelope responses.
128
+ const result = fetchResult.data.value
129
+ state.result = result?.data ?? result
130
+ } finally {
131
+ state.loading = false
132
+ }
133
+ }
134
+
135
+ function getValue(lang = null) {
136
+ let val = props.params.boneState.bonevalue
137
+ if (props.params.index !== null) {
138
+ if (lang) {
139
+ val = val?.[lang]
140
+ val = val?.[props.params.index]
141
+ }
142
+ } else if (lang) {
143
+ val = val?.[lang]
144
+ }
145
+ return val
146
+ }
147
+
148
+ onMounted(() => {
149
+ state.value_de = getValue("de")
150
+ state.currentLang = state.nextlang
151
+ if (state.nextlang !== "de") {
152
+ state.currentLang = props.params.boneState.currentLanguage
153
+ }
154
+ state.result = getValue(state.currentLang)
155
+ })
156
+
157
+ watch(
158
+ () => getValue("de"),
159
+ (newVal) => {
160
+ state.value_de = newVal
161
+ }
162
+ )
163
+
164
+ function updateValue(e) {
165
+ state.result = e.target.value
166
+ }
167
+ function updateValueDe(e) {
168
+ state.value_de = e.target.value
169
+ }
170
+
171
+ function nextlang() {
172
+ emit("next", state.result, state.currentLang)
173
+ state.currentLang = state.nextlang
174
+ state.result = getValue(state.currentLang)
175
+ }
176
+
177
+ function CloseAction() {
178
+ state.result = null
179
+ emit("close")
180
+ }
181
+
182
+ function ApplySelection() {
183
+ emit("close", state.result, state.currentLang)
184
+ }
185
+ </script>
186
+
187
+ <style scoped>
188
+ .translate-wrapper {
189
+ padding: var(--wa-space-l);
190
+ display: flex;
191
+ flex-direction: column;
192
+ gap: var(--wa-space-s);
193
+ }
194
+
195
+ .translate-grid {
196
+ display: grid;
197
+ grid-template-columns: minmax(0, 1fr) 3em minmax(0, 1fr);
198
+ }
199
+
200
+ .translate-flex {
201
+ display: flex;
202
+ flex-direction: column;
203
+ gap: var(--wa-space-xs);
204
+ }
205
+
206
+ .translate-icon-wrap {
207
+ display: flex;
208
+ flex-direction: column;
209
+ align-items: center;
210
+ justify-content: center;
211
+ }
212
+
213
+ .translate-footer {
214
+ display: grid;
215
+ grid-template-columns: minmax(0, 1fr) 3em minmax(0, 1fr);
216
+ }
217
+
218
+ .translate-small-print {
219
+ font-size: 0.7em;
220
+ }
221
+
222
+ wa-textarea {
223
+ &::part(form-control-label) {
224
+ margin-bottom: var(--wa-space-xs);
225
+ font-weight: 600;
226
+ }
227
+ }
228
+
229
+ .translate-dialog-footer {
230
+ display: flex;
231
+ flex-direction: row;
232
+ gap: var(--wa-space-s);
233
+ }
234
+
235
+ .translate-dialog-footer-spacer {
236
+ flex: 1;
237
+ }
238
+ </style>