mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-10-20 18:59:33 +00:00
dms upload input preview prop on core component; use medium sized preview for pdf in iframe, image file in <img> tag; split entschuldigung von/bis from 2 datetime inputs into 2 date and 2 time input since this is apparently a usability issue; changed validation for this in order to verify both chronologically; also added validation for this to backend; since assistenz can edit these exact values, also backend validate on updateEntschuldigung in AdministrationApi.php;
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
import DmsItem from './Dms/Item.js';
|
||||
import DmsPreview from './Dms/Preview.js';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
DmsItem
|
||||
DmsItem,
|
||||
DmsPreview
|
||||
},
|
||||
emits: [
|
||||
'update:modelValue'
|
||||
@@ -24,6 +26,21 @@ export default {
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// shows the chosen images and pdfs below the input before the upload
|
||||
preview: Boolean,
|
||||
// small, medium, large or a css length like '400px'
|
||||
previewHeight: {
|
||||
type: String,
|
||||
default: 'medium'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
previewFiles() {
|
||||
if (!this.preview || !this.modelValue)
|
||||
return [];
|
||||
// stored dms files are json placeholders, they have no content to show
|
||||
return Array.from(this.modelValue).filter(file => file instanceof File && file.type != 'application/x.fhc-dms+json');
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -103,5 +120,6 @@ export default {
|
||||
>
|
||||
</dms-item>
|
||||
</ul>
|
||||
<dms-preview v-for="(file, index) in previewFiles" :key="index" :file="file" :height="previewHeight"></dms-preview>
|
||||
</div>`
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// only these types get a preview. html or svg in the iframe would run their scripts in the page origin
|
||||
const IMAGE_TYPES = ['image/png', 'image/jpeg', 'image/gif', 'image/webp'];
|
||||
|
||||
const HEIGHTS = {
|
||||
small: '30vh',
|
||||
medium: '50vh',
|
||||
large: '80vh'
|
||||
};
|
||||
|
||||
/**
|
||||
* Preview of one chosen file before the upload: an image as img, a pdf in the pdf viewer of the browser.
|
||||
* height: small, medium, large or a css length like '400px'.
|
||||
*/
|
||||
export default {
|
||||
props: {
|
||||
file: {
|
||||
type: File,
|
||||
required: true
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: 'medium'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
url: ''
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isImage() {
|
||||
return IMAGE_TYPES.includes(this.file.type);
|
||||
},
|
||||
// android chrome has no inline pdf viewer, there a pdf gets no preview
|
||||
isPdf() {
|
||||
return this.file.type == 'application/pdf' && navigator.pdfViewerEnabled !== false;
|
||||
},
|
||||
cssHeight() {
|
||||
return HEIGHTS[this.height] || this.height;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
file: {
|
||||
handler() {
|
||||
this.revokeUrl();
|
||||
// an object url only references the file, no base64 copy in memory
|
||||
if (this.isImage || this.isPdf)
|
||||
this.url = URL.createObjectURL(this.file);
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
unmounted() {
|
||||
this.revokeUrl();
|
||||
},
|
||||
methods: {
|
||||
revokeUrl() {
|
||||
if (this.url)
|
||||
URL.revokeObjectURL(this.url);
|
||||
this.url = '';
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div v-if="url" class="form-upload-dms-preview mt-2">
|
||||
<img v-if="isImage" :src="url" :alt="file.name" class="img-fluid border rounded" :style="{ maxHeight: cssHeight }">
|
||||
<iframe v-else :src="url" :title="file.name" class="d-block w-100 border rounded" :style="{ height: cssHeight }"></iframe>
|
||||
</div>`
|
||||
}
|
||||
@@ -33136,6 +33136,26 @@ array(
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'anwesenheiten',
|
||||
'category' => 'global',
|
||||
'phrase' => 'errorValidateUhrzeit',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Die Endzeit muss nach der Startzeit liegen.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'The end time must be after the start time.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'anwesenheiten',
|
||||
'category' => 'global',
|
||||
|
||||
Reference in New Issue
Block a user