Merge branch 'feature-30660/FHC4_StudierendenGUI_Prototyp' of github.com:FH-Complete/FHC-Core into feature-30660/FHC4_StudierendenGUI_Prototyp

Update Routine
This commit is contained in:
ma0068
2024-01-19 15:20:12 +01:00
6 changed files with 151 additions and 16 deletions
+60 -3
View File
@@ -1,11 +1,68 @@
.text-prewrap {
white-space: pre-line;
white-space: pre-line;
}
.btn-p-0 {
padding: 0 .375rem;
padding: 0 .375rem;
}
.z-1 {
z-index: 1;
z-index: 1;
}
.input-group > .input-group-item {
position: relative;
flex: 1 1 auto;
width: 1%;
min-width: 0;
}
.input-group > .input-group-item .form-control:focus,
.input-group > .input-group-item .form-select:focus {
z-index: 3;
position: relative;
}
.input-group-lg > .input-group-item .form-control,
.input-group-lg > .input-group-item .form-select {
padding: 0.5rem 1rem;
font-size: 1.25rem;
border-radius: 0.3rem;
}
.input-group-sm > .input-group-item .form-control,
.input-group-sm > .input-group-item .form-select {
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
border-radius: 0.2rem;
}
.input-group-lg > .input-group-item .form-select,
.input-group-sm > .input-group-item .form-select {
padding-right: 3rem;
}
.input-group:not(.has-validation) > .input-group-item:not(:last-child) .form-control,
.input-group:not(.has-validation) > .input-group-item:not(:last-child) .form-select {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.input-group.has-validation > .input-group-item:nth-last-child(n+3) .form-control,
.input-group.has-validation > .input-group-item:nth-last-child(n+3) .form-select {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.input-group > .input-group-item:not(:first-child) .form-control,
.input-group > .input-group-item:not(:first-child) .form-select {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.form-control-color.is-invalid,
.was-validated .form-control-color:invalid,
.form-control-color.is-valid,
.was-validated .form-control-color:valid {
padding-right: .375rem;
background-image: none;
}
+11
View File
@@ -5664,3 +5664,14 @@
}
/* Customizations to the designer theme should be defined here */
.p-inputtext {
padding: 0.375rem 0.75rem;
}
.p-inputtext:enabled:focus {
color: #212529;
background-color: #fff;
border-color: #86b7fe;
outline: 0;
box-shadow: 0 0 0 .25rem rgba(13,110,253,.25);
}
+8
View File
@@ -30,6 +30,14 @@ export default {
if (!a[name])
a[name] = [];
a[name].push(c);
if (c.lcType == 'checkbox' && name.substr(-1) == ']' && name.indexOf('[')) {
name = name.substr(0, name.lastIndexOf('['));
if (!a[name])
a[name] = [];
a[name].push(c);
}
return a;
}, {});
}
+64 -7
View File
@@ -13,6 +13,8 @@ export default {
props: {
bsFeedback: Boolean,
noAutoClass: Boolean,
noFeedback: Boolean,
inputGroup: Boolean,
type: String,
name: String,
containerClass: [String, Array, Object]
@@ -29,8 +31,38 @@ export default {
return true;
if (this.containerClass)
return true;
if (this.autoContainerClass)
return true;
return false;
},
acc() {
if (!this.containerClass)
return {};
if (typeof this.containerClass === 'string' || this.containerClass instanceof String)
return this.containerClass.split(' ').reduce((a,c) => {a[c] = true; return a}, {});
if (Array.isArray(this.containerClass))
return this.containerClass.reduce((a,c) => {a[c] = true; return a}, {});
return this.containerClass;
},
autoContainerClass() {
if (this.noAutoClass)
return this.acc;
const acc = {...this.acc};
if (this.inputGroup)
acc['input-group-item'] = true;
if (this.lcType == 'radio' || this.lcType == 'checkbox')
acc['form-check'] = true;
if (this.inputGroup && acc['form-check']) {
acc['input-group-item'] = false;
acc['form-check'] = false;
acc['input-group-text'] = true;
}
return acc;
},
lcType() {
if (!this.type)
return 'text';
@@ -47,6 +79,9 @@ export default {
return 'PvAutocomplete';
case 'uploadimage':
return 'UploadImage';
case 'uploadfile':
case 'uploaddms':
return 'UploadDms';
default:
return 'input';
}
@@ -80,7 +115,12 @@ export default {
case 'datepicker':
classes.push('p-0');
classes.push('border-0');
case 'color':
if (!c.includes('form-control-color'))
classes.push('form-control-color');
case 'text':
case 'number':
case 'password':
case 'textarea':
if (!c.includes('form-control'))
classes.push('form-control');
@@ -146,6 +186,8 @@ export default {
this._.components.PvAutocomplete = Vue.defineAsyncComponent(() => import(FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + "/public/js/components/primevue/autocomplete/autocomplete.esm.min.js"));
} else if (this.tag == 'UploadImage' && !this._.components.UploadImage) {
this._.components.UploadImage = Vue.defineAsyncComponent(() => import("./Upload/Image.js"));
} else if (this.tag == 'UploadDms' && !this._.components.UploadDms) {
this._.components.UploadDms = Vue.defineAsyncComponent(() => import("./Upload/Dms.js"));
}
}
},
@@ -158,10 +200,9 @@ export default {
mounted() {
if (this.$registerToForm)
this.$registerToForm(this);
// TODO(chris): wrap check in div?
},
template: `
<component :is="!hasContainer ? 'FhcFragment' : 'div'" class="position-relative" :class="containerClass">
<component :is="!hasContainer ? 'FhcFragment' : 'div'" class="position-relative" :class="autoContainerClass">
<label v-if="$attrs.label && lcType != 'radio' && lcType != 'checkbox'" :for="idCmp">{{$attrs.label}}</label>
<input v-if="tag == 'input'" :type="lcType" v-model="modelValueCmp" v-bind="$attrs" :id="idCmp" :name="name" :class="validationClass" :modelValue="undefined" @input="clearValidation(); $emit('input', $event)">
<textarea v-else-if="tag == 'textarea'" v-model="modelValueCmp" v-bind="$attrs" :id="idCmp" :name="name" :class="validationClass" :modelValue="undefined" @input="clearValidation(); $emit('input', $event)"></textarea>
@@ -174,10 +215,11 @@ export default {
:type="type"
v-model="modelValueCmp"
v-bind="$attrs"
:uid="idCmp.substr(9)"
:uid="idCmp ? idCmp.substr(9) : idCmp"
:name="name"
:class="validationClass"
:input-class-name="[...Object.entries({'form-control': !noAutoClass, 'is-valid': valid === true, 'is-invalid': valid === false}).reduce((a,[k,v]) => {if(v) a.push(k);return a}, []), ...($attrs['input-class-name'] ? $attrs['input-class-name'].split(' ') : [])].join(' ')"
:input-class-name=
"[...Object.entries({'form-control': !noAutoClass, 'is-valid': valid === true, 'is-invalid': valid === false}).reduce((a,[k,v]) => {if(v) a.push(k);return a}, []), ...($attrs['input-class-name'] ? $attrs['input-class-name'].split(' ') : [])].join(' ')"
@update:model-value="clearValidation"
>
<slot></slot>
@@ -189,13 +231,28 @@ export default {
v-model="modelValueCmp"
v-bind="$attrs"
:id="idCmp"
:name="name"
:input-props="{name}"
:class="validationClass"
:input-class="[...Object.entries({'form-control': !noAutoClass, 'is-valid': valid === true, 'is-invalid': valid === false}).reduce((a,[k,v]) => {if(v) a.push(k);return a}, []), ...($attrs['input-class'] ? $attrs['input-class'].split(' ') : [])].join(' ')"
@update:model-value="clearValidation"
>
<slot></slot>
</component>
<component
v-else-if="tag == 'UploadDms'"
:is="tag"
:type="type"
v-model="modelValueCmp"
v-bind="$attrs"
:id="idCmp"
:name="name"
:class="validationClass"
:input-class="validationClass"
:no-list="inputGroup"
@update:model-value="clearValidation"
>
<slot></slot>
</component>
<component
v-else
:is="tag"
@@ -209,13 +266,13 @@ export default {
>
<slot></slot>
</component>
<div v-if="valid !== undefined && feedback.length" :class="feedbackClass">
<label v-if="$attrs.label && (lcType == 'radio' || lcType == 'checkbox')" :for="idCmp" :class="!noAutoClass && 'form-check-label'">{{$attrs.label}}</label>
<div v-if="valid !== undefined && feedback.length && !noFeedback" :class="feedbackClass">
<template v-for="(msg, i) in feedback" :key="i">
<hr v-if="i" class="m-0">
{{msg}}
</template>
</div>
<label v-if="$attrs.label && (lcType == 'radio' || lcType == 'checkbox')" :for="idCmp" :class="!noAutoClass && 'form-check-label'">{{$attrs.label}}</label>
</component>
`
}
+5 -3
View File
@@ -9,7 +9,9 @@ export default {
},
multiple: Boolean,
id: String,
name: String
name: String,
inputClass: [String, Array, Object],
noList: Boolean
},
methods: {
stringifyFile(file) {
@@ -71,8 +73,8 @@ export default {
},
template: `
<div class="form-upload-dms">
<input ref="upload" class="form-control" :id="id" :name="name" :multiple="multiple" type="file" @change="addFiles">
<ul v-if="modelValue.length && multiple" class="list-unstyled m-0">
<input ref="upload" class="form-control" :class="inputClass" :id="id" :name="name" :multiple="multiple" type="file" @change="addFiles">
<ul v-if="modelValue.length && multiple && !noList" class="list-unstyled m-0">
<li v-for="(file, index) in modelValue" :key="index" class="d-flex mx-1 mt-1">
<span class="col-auto"><i class="fa fa-file me-1"></i></span>
<span class="col">{{ file.name }}</span>
+3 -3
View File
@@ -12,7 +12,7 @@ export default {
],
props: {
// TODO(chris): rename to config?
configUrl: {
config: {
type: [String, Object],
required: true
},
@@ -43,7 +43,7 @@ export default {
}
},
watch: {
configUrl(n) {
config(n) {
this.initConfig(n);
}
},
@@ -101,7 +101,7 @@ export default {
}
},
created() {
this.initConfig(this.configUrl);
this.initConfig(this.config);
},
template: `
<div class="fhc-tabs d-flex" :class="vertical ? 'align-items-stretch' : 'flex-column'" v-if="Object.keys(tabs).length">