show image loader/errors

This commit is contained in:
2023-07-28 13:46:28 +10:00
parent c1fb03add1
commit 250401fd62

View File

@@ -1,9 +1,22 @@
<template>
<div class="flex flex-col flex-1 flex-align-center">
<label class="control-label" v-bind="{ for: id }">{{ label }}</label>
<div v-if="mediaUrl?.length > 0" class="text-center mb-4">
<div v-if="value" class="flex flex-justify-center mb-4">
<SMLoading v-if="!imgError && !imgLoaded" class="w-48 h-48" small />
<svg
v-if="imgError"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
class="h-48 text-gray">
<path
d="M20 17H22V15H20V17M20 7V13H22V7M6 16H11V18H6M6 12H14V14H6M4 2C2.89 2 2 2.89 2 4V20C2 21.11 2.89 22 4 22H16C17.11 22 18 21.11 18 20V8L12 2M4 4H11V9H16V20H4Z"
fill="currentColor" />
</svg>
<img
v-if="!imgError"
class="max-w-48 max-h-48"
@load="imgLoaded = true"
@error="imgError = true"
:src="mediaGetThumbnail(value, 'medium')" />
</div>
<svg
@@ -29,13 +42,14 @@
</template>
<script setup lang="ts">
import { inject, watch, ref, useSlots, computed } from "vue";
import { inject, watch, ref, useSlots } from "vue";
import { isEmpty, generateRandomElementId } from "../helpers/utils";
import { toTitleCase } from "../helpers/string";
import { mediaGetThumbnail } from "../helpers/media";
import { openDialog } from "./SMDialog";
import SMDialogMedia from "./dialogs/SMDialogMedia.vue";
import { Media } from "../helpers/api.types";
import SMLoading from "./SMLoading.vue";
const emits = defineEmits(["update:modelValue", "blur", "keyup"]);
const props = defineProps({
@@ -183,21 +197,16 @@ const id = ref(
: generateRandomElementId(),
);
const feedbackInvalid = ref(props.feedbackInvalid);
const active = ref(value.value?.toString().length ?? 0 > 0);
const focused = ref(false);
const disabled = ref(props.disabled);
watch(
() => value.value,
(newValue) => {
mediaUrl.value = value.value.url ?? "";
},
);
const imgLoaded = ref(false);
const imgError = ref(false);
if (props.modelValue != undefined) {
watch(
() => props.modelValue,
(newValue) => {
imgLoaded.value = false;
imgError.value = false;
value.value = newValue;
},
);
@@ -246,62 +255,6 @@ if (form) {
);
}
const mediaUrl = ref(value.value.url ?? "");
const handleFocus = () => {
active.value = true;
focused.value = true;
};
const handleBlur = async () => {
active.value = value.value?.length ?? 0 > 0;
focused.value = false;
emits("blur");
if (control) {
await control.validate();
control.isValid();
}
};
const handleCheckbox = (event: Event) => {
const target = event.target as HTMLInputElement;
value.value = target.checked;
emits("update:modelValue", target.checked);
if (control) {
control.value = target.checked;
feedbackInvalid.value = "";
}
};
const handleInput = (event: Event) => {
const target = event.target as HTMLInputElement;
value.value = target.value;
emits("update:modelValue", target.value);
if (control) {
control.value = target.value;
feedbackInvalid.value = "";
}
};
const handleKeyup = (event: Event) => {
emits("keyup", event);
};
const handleClear = () => {
value.value = "";
emits("update:modelValue", "");
};
const handleChange = (event) => {
if (control) {
control.value = event.target.files[0];
feedbackInvalid.value = "";
}
};
const handleMediaSelect = async () => {
let result = await openDialog(SMDialogMedia, {
allowUpload: props.allowUpload,
@@ -309,7 +262,6 @@ const handleMediaSelect = async () => {
});
if (result) {
const mediaResult = result as Media;
mediaUrl.value = mediaResult.url;
emits("update:modelValue", mediaResult);
if (control) {
control.value = mediaResult;
@@ -317,29 +269,6 @@ const handleMediaSelect = async () => {
}
}
};
const computedAutocompleteItems = computed(() => {
let autocompleteList = [];
if (props.autocomplete) {
if (typeof props.autocomplete === "function") {
autocompleteList = props.autocomplete(value.value);
} else {
autocompleteList = props.autocomplete.filter((str) =>
str.includes(value.value),
);
}
return autocompleteList.sort((a, b) => a.localeCompare(b));
}
return autocompleteList;
});
const handleAutocompleteClick = (item) => {
value.value = item;
emits("update:modelValue", item);
};
</script>
<style lang="scss">