bug fixes and support new media
This commit is contained in:
@@ -1,44 +1,49 @@
|
||||
<template>
|
||||
<SMContainer class="sm-attachments">
|
||||
<h3 v-if="props.attachments && props.attachments.length > 0">Files</h3>
|
||||
<div
|
||||
v-for="file of props.attachments"
|
||||
:key="file.id"
|
||||
class="sm-attachment-row">
|
||||
<div class="sm-attachment-file-icon">
|
||||
<img
|
||||
:src="getFileIconImagePath(file.title || file.name)"
|
||||
height="48"
|
||||
width="48" />
|
||||
</div>
|
||||
<a
|
||||
:href="file.url"
|
||||
target="_blank"
|
||||
class="sm-attachment-file-name"
|
||||
>{{ file.title || file.name }}</a
|
||||
>
|
||||
<a :href="file.url + '?download=1'" class="sm-attachment-download"
|
||||
><svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M12 10V20M12 20L9.5 17.5M12 20L14.5 17.5"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round" />
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M6.3218 7.05726C7.12925 4.69709 9.36551 3 12 3C14.6345 3 16.8708 4.69709 17.6782 7.05726C19.5643 7.37938 21 9.02203 21 11C21 13.2091 19.2091 15 17 15H16C15.4477 15 15 14.5523 15 14C15 13.4477 15.4477 13 16 13H17C18.1046 13 19 12.1046 19 11C19 9.89543 18.1046 9 17 9C16.9776 9 16.9552 9.00037 16.9329 9.0011C16.4452 9.01702 16.0172 8.67854 15.9202 8.20023C15.5502 6.37422 13.9345 5 12 5C10.0655 5 8.44979 6.37422 8.07977 8.20023C7.98284 8.67854 7.55482 9.01702 7.06706 9.0011C7.04476 9.00037 7.02241 9 7 9C5.89543 9 5 9.89543 5 11C5 12.1046 5.89543 13 7 13H8C8.55228 13 9 13.4477 9 14C9 14.5523 8.55228 15 8 15H7C4.79086 15 3 13.2091 3 11C3 9.02203 4.43567 7.37938 6.3218 7.05726Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</a>
|
||||
<div class="sm-attachment-file-size">
|
||||
({{ bytesReadable(file.size) }})
|
||||
</div>
|
||||
</div>
|
||||
<table class="sm-attachment-list">
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="file of props.attachments"
|
||||
:key="file.id"
|
||||
class="sm-attachment-row">
|
||||
<td class="sm-attachment-file-icon">
|
||||
<img
|
||||
:src="getFileIconImagePath(file.title || file.name)"
|
||||
height="48"
|
||||
width="48" />
|
||||
</td>
|
||||
<td class="sm-attachment-file-name">
|
||||
<a :href="file.url" target="_blank">{{
|
||||
file.title || file.name
|
||||
}}</a>
|
||||
</td>
|
||||
<td class="sm-attachment-download">
|
||||
<a :href="file.url + '?download=1'"
|
||||
><svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M12 10V20M12 20L9.5 17.5M12 20L14.5 17.5"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round" />
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M6.3218 7.05726C7.12925 4.69709 9.36551 3 12 3C14.6345 3 16.8708 4.69709 17.6782 7.05726C19.5643 7.37938 21 9.02203 21 11C21 13.2091 19.2091 15 17 15H16C15.4477 15 15 14.5523 15 14C15 13.4477 15.4477 13 16 13H17C18.1046 13 19 12.1046 19 11C19 9.89543 18.1046 9 17 9C16.9776 9 16.9552 9.00037 16.9329 9.0011C16.4452 9.01702 16.0172 8.67854 15.9202 8.20023C15.5502 6.37422 13.9345 5 12 5C10.0655 5 8.44979 6.37422 8.07977 8.20023C7.98284 8.67854 7.55482 9.01702 7.06706 9.0011C7.04476 9.00037 7.02241 9 7 9C5.89543 9 5 9.89543 5 11C5 12.1046 5.89543 13 7 13H8C8.55228 13 9 13.4477 9 14C9 14.5523 8.55228 15 8 15H7C4.79086 15 3 13.2091 3 11C3 9.02203 4.43567 7.37938 6.3218 7.05726Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</a>
|
||||
</td>
|
||||
<td class="sm-attachment-file-size">
|
||||
({{ bytesReadable(file.size) }})
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</SMContainer>
|
||||
</template>
|
||||
|
||||
@@ -57,43 +62,92 @@ const props = defineProps({
|
||||
|
||||
<style lang="scss">
|
||||
.sm-attachments {
|
||||
display: block;
|
||||
|
||||
h3 {
|
||||
margin-top: map-get($spacer, 4);
|
||||
margin-bottom: 0;
|
||||
margin-bottom: map-get($spacer, 3);
|
||||
}
|
||||
|
||||
.sm-attachment-row {
|
||||
border-bottom: 1px solid $secondary-background-color;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.5rem 0;
|
||||
.sm-attachment-list {
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
max-width: 580px;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
.sm-attachment-row {
|
||||
td {
|
||||
border-bottom: 1px solid $secondary-background-color;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.sm-attachment-file-icon {
|
||||
display: flex;
|
||||
width: 64px;
|
||||
justify-content: center;
|
||||
}
|
||||
&:last-child td {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.sm-attachment-download {
|
||||
margin-left: 0.75rem;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
color: $secondary-color-dark;
|
||||
transition: color 0.2s ease-in-out;
|
||||
.sm-attachment-file-icon {
|
||||
width: 64px;
|
||||
|
||||
&:hover {
|
||||
color: $primary-color-dark;
|
||||
img {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.sm-attachment-file-name {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.sm-attachment-download {
|
||||
width: 28px;
|
||||
text-align: center;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
color: $secondary-color-dark;
|
||||
transition: color 0.2s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
color: $primary-color-dark;
|
||||
}
|
||||
|
||||
svg {
|
||||
margin-top: 4px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sm-attachment-file-size {
|
||||
width: 84px;
|
||||
font-size: 75%;
|
||||
color: $secondary-color-dark;
|
||||
white-space: nowrap;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 640px) {
|
||||
.sm-attachments .sm-attachment-list {
|
||||
.sm-attachment-file-icon img {
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
.sm-attachment-download a,
|
||||
.sm-attachment-file-size {
|
||||
font-size: 75%;
|
||||
margin-left: 0.75rem;
|
||||
color: $secondary-color-dark;
|
||||
padding-left: 0.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 440px) {
|
||||
.sm-attachments .sm-attachment-list {
|
||||
.sm-attachment-file-icon {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
<template>
|
||||
<div class="sm-carousel-slide" :style="styleObject">
|
||||
<div
|
||||
v-if="image.length > 0 && imageUrl.length == 0"
|
||||
class="sm-carousel-slide-loading">
|
||||
<SMLoadingIcon />
|
||||
</div>
|
||||
<div v-else class="sm-carousel-slide-body">
|
||||
<div class="sm-carousel-slide-body">
|
||||
<div class="sm-carousel-slide-content">
|
||||
<div class="sm-carousel-slide-content-inner">
|
||||
<h3>{{ title }}</h3>
|
||||
@@ -24,12 +19,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from "vue";
|
||||
import { api } from "../helpers/api";
|
||||
import { MediaResponse } from "../helpers/api.types";
|
||||
import { imageLoad, imageXLarge } from "../helpers/image";
|
||||
import SMButton from "./SMButton.vue";
|
||||
import SMLoadingIcon from "./SMLoadingIcon.vue";
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
@@ -59,43 +49,12 @@ const props = defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
let imageUrl = ref("");
|
||||
|
||||
/**
|
||||
* Carousel slide styles.
|
||||
*/
|
||||
let styleObject = {};
|
||||
|
||||
/**
|
||||
* Load the slider data.
|
||||
*/
|
||||
const handleLoad = () => {
|
||||
imageUrl.value = "";
|
||||
|
||||
api.get({ url: "/media/{medium}", params: { medium: props.image } })
|
||||
.then((result) => {
|
||||
const data = result.data as MediaResponse;
|
||||
|
||||
if (data && data.medium) {
|
||||
imageLoad(data.medium.url, (url) => {
|
||||
imageUrl.value = url;
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
/* empty */
|
||||
});
|
||||
let styleObject = {
|
||||
backgroundImage: `url('${props.image}')`,
|
||||
};
|
||||
|
||||
watch(
|
||||
() => imageUrl.value,
|
||||
(value) => {
|
||||
const url = imageXLarge(value);
|
||||
styleObject["backgroundImage"] = `url('${url}')`;
|
||||
}
|
||||
);
|
||||
|
||||
handleLoad();
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -53,6 +53,7 @@ import { api } from "../helpers/api";
|
||||
import { MediaCollection, MediaResponse } from "../helpers/api.types";
|
||||
import { routes } from "../router";
|
||||
import { urlMatches } from "../helpers/url";
|
||||
import { mediaGetVariantUrl } from "../helpers/media";
|
||||
|
||||
interface PageList {
|
||||
title: string;
|
||||
@@ -390,40 +391,6 @@ const imageBrowser = (callback, value, meta, gallery = false) => {
|
||||
var title = "";
|
||||
var itemsFound = 0;
|
||||
|
||||
// Open a dialog to select a file
|
||||
const input = document.createElement("input");
|
||||
input.setAttribute("type", "file");
|
||||
input.setAttribute("accept", "image/*");
|
||||
input.onchange = function () {
|
||||
if (input.files) {
|
||||
let formData = new FormData();
|
||||
formData.append("file", input.files[0]);
|
||||
|
||||
api.post({
|
||||
url: "/media",
|
||||
body: formData,
|
||||
})
|
||||
.then((result) => {
|
||||
input.value = "";
|
||||
const data = result.data as MediaResponse;
|
||||
|
||||
if (data.medium) {
|
||||
callback(data.medium.url);
|
||||
dialog.close();
|
||||
} else {
|
||||
alert("The server responded with an unknown error");
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
input.value = "";
|
||||
alert(
|
||||
error.data.message ||
|
||||
"An unexpected error occurred uploading the file to the server."
|
||||
);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const updateFooter = () => {
|
||||
let selectedText = "";
|
||||
|
||||
@@ -563,7 +530,10 @@ const imageBrowser = (callback, value, meta, gallery = false) => {
|
||||
|
||||
const image = document.createElement("div");
|
||||
image.classList.add("image-library-content-item-image");
|
||||
image.style.backgroundImage = `url('${medium.url}?w=200')`;
|
||||
image.style.backgroundImage = `url('${mediaGetVariantUrl(
|
||||
medium,
|
||||
"small"
|
||||
)}')`;
|
||||
|
||||
const title = document.createElement("div");
|
||||
title.classList.add("image-library-content-item-title");
|
||||
@@ -614,7 +584,7 @@ const imageBrowser = (callback, value, meta, gallery = false) => {
|
||||
|
||||
const image = document.createElement("div");
|
||||
image.classList.add("image-gallery-content-item-image");
|
||||
image.style.backgroundImage = `url('${url}?w=200')`;
|
||||
image.style.backgroundImage = `url('${url}')`;
|
||||
|
||||
const title = document.createElement("div");
|
||||
title.classList.add("image-gallery-content-item-title");
|
||||
@@ -639,6 +609,8 @@ const imageBrowser = (callback, value, meta, gallery = false) => {
|
||||
}
|
||||
};
|
||||
|
||||
console.log(selected);
|
||||
|
||||
const rightBtn = document.createElement("div");
|
||||
rightBtn.classList.add("image-gallery-content-item-right");
|
||||
rightBtn.onclick = function () {
|
||||
@@ -747,42 +719,128 @@ const imageBrowser = (callback, value, meta, gallery = false) => {
|
||||
callback(selected);
|
||||
dialog.close();
|
||||
},
|
||||
onChange: function (dialogApi, details) {
|
||||
onChange: async function (dialogApi, details) {
|
||||
if (details.name == "dropzone") {
|
||||
const files = dialogApi.getData().dropzone || [];
|
||||
if (files && files.length > 0) {
|
||||
let formData = new FormData();
|
||||
formData.append("file", files[0]);
|
||||
const uploadElem = document.createElement("div");
|
||||
uploadElem.classList.add("image-gallery-content-upload");
|
||||
document
|
||||
.getElementsByTagName("body")[0]
|
||||
.appendChild(uploadElem);
|
||||
|
||||
api.post({
|
||||
url: "/media",
|
||||
body: formData,
|
||||
})
|
||||
.then((result) => {
|
||||
input.value = "";
|
||||
const data = result.data as MediaResponse;
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
let formData = new FormData();
|
||||
formData.append("file", files[0]);
|
||||
|
||||
if (data.medium) {
|
||||
if (gallery == false) {
|
||||
callback(data.medium.url);
|
||||
dialog.close();
|
||||
} else {
|
||||
selected.push(data.medium.url);
|
||||
dialogApi.showTab("gallery");
|
||||
try {
|
||||
let progressText = [
|
||||
`Uploading File ${i + 1}/${files.length}`,
|
||||
"",
|
||||
];
|
||||
|
||||
let result = await api.post({
|
||||
url: "/media",
|
||||
body: formData,
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
progress: (progressData) => {
|
||||
progressText[1] = `${Math.floor(
|
||||
(progressData.loaded /
|
||||
progressData.total) *
|
||||
100
|
||||
)}%`;
|
||||
uploadElem.innerHTML =
|
||||
progressText.join("<br />");
|
||||
},
|
||||
});
|
||||
|
||||
if (result.data) {
|
||||
const data = result.data as MediaResponse;
|
||||
|
||||
if (
|
||||
data.medium.status != "" &&
|
||||
data.medium.status.startsWith("Failed") ==
|
||||
false
|
||||
) {
|
||||
progressText[1] = `${data.medium.status}...`;
|
||||
uploadElem.innerHTML =
|
||||
progressText.join("<br />");
|
||||
|
||||
let mediaProcessed = false;
|
||||
|
||||
while (mediaProcessed == false) {
|
||||
await new Promise((resolve) =>
|
||||
setTimeout(resolve, 500)
|
||||
);
|
||||
|
||||
try {
|
||||
let updateResult = await api.get({
|
||||
url: "/media/{id}",
|
||||
params: {
|
||||
id: data.medium.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (updateResult.data) {
|
||||
const updateData =
|
||||
updateResult.data as MediaResponse;
|
||||
if (
|
||||
updateData.medium.status ==
|
||||
"" &&
|
||||
data.medium.status.startsWith(
|
||||
"Failed"
|
||||
) == false
|
||||
) {
|
||||
mediaProcessed = true;
|
||||
|
||||
if (gallery == false) {
|
||||
callback(
|
||||
mediaGetVariantUrl(
|
||||
updateData.medium
|
||||
)
|
||||
);
|
||||
dialog.close();
|
||||
} else {
|
||||
selected.push(
|
||||
mediaGetVariantUrl(
|
||||
updateData.medium
|
||||
)
|
||||
);
|
||||
dialogApi.showTab(
|
||||
"gallery"
|
||||
);
|
||||
}
|
||||
} else {
|
||||
progressText[1] = `${updateData.medium.status}...`;
|
||||
uploadElem.innerHTML =
|
||||
progressText.join(
|
||||
"<br />"
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw "error";
|
||||
}
|
||||
} catch {
|
||||
mediaProcessed = true;
|
||||
alert(
|
||||
"An server error occurred processing the file"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
alert(
|
||||
"The server responded with an unknown error"
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
} catch (error) {
|
||||
input.value = "";
|
||||
alert(
|
||||
error.data.message ||
|
||||
"An unexpected error occurred uploading the file to the server."
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
uploadElem.parentNode.removeChild(uploadElem);
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1039,6 +1097,22 @@ const imageBrowser = (callback, value, meta, gallery = false) => {
|
||||
}
|
||||
}
|
||||
|
||||
.image-gallery-content-upload {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: #ffffffe8;
|
||||
color: #000000;
|
||||
z-index: 10000;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
line-height: 2rem;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
|
||||
@@ -96,6 +96,7 @@ import { toTitleCase } from "../helpers/string";
|
||||
import { isEmpty } from "../helpers/utils";
|
||||
import { isUUID } from "../helpers/uuid";
|
||||
import SMDialogMedia from "./dialogs/SMDialogMedia.vue";
|
||||
import { mediaGetVariantUrl } from "../helpers/media";
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
@@ -226,25 +227,30 @@ watch(
|
||||
watch(
|
||||
() => value.value,
|
||||
async (newValue) => {
|
||||
inputActive.value = newValue.length > 0;
|
||||
if (newValue) {
|
||||
inputActive.value = newValue.length > 0;
|
||||
|
||||
if (props.type == "media") {
|
||||
if (isUUID(newValue)) {
|
||||
try {
|
||||
const result = await api.get({
|
||||
url: "/media/{id}",
|
||||
params: {
|
||||
id: newValue,
|
||||
},
|
||||
});
|
||||
if (props.type == "media") {
|
||||
if (isUUID(newValue)) {
|
||||
try {
|
||||
const result = await api.get({
|
||||
url: "/media/{id}",
|
||||
params: {
|
||||
id: newValue,
|
||||
},
|
||||
});
|
||||
|
||||
const data = result.data as MediaResponse;
|
||||
const data = result.data as MediaResponse;
|
||||
|
||||
if (data && data.medium) {
|
||||
mediaUrl.value = imageMedium(data.medium.url);
|
||||
if (data && data.medium) {
|
||||
mediaUrl.value = mediaGetVariantUrl(
|
||||
data.medium,
|
||||
"small"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
/* empty */
|
||||
}
|
||||
} catch (error) {
|
||||
/* empty */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,6 @@
|
||||
{{ computedMonth }}
|
||||
</div>
|
||||
</div>
|
||||
<ion-icon
|
||||
v-if="imageUrl.length == 0"
|
||||
class="sm-panel-image-loader"
|
||||
name="image-outline" />
|
||||
</div>
|
||||
<div class="sm-panel-body">
|
||||
<h3 class="sm-panel-title">{{ title }}</h3>
|
||||
@@ -56,18 +52,14 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref, watch } from "vue";
|
||||
import { api } from "../helpers/api";
|
||||
import { MediaResponse } from "../helpers/api.types";
|
||||
import { computed } from "vue";
|
||||
import { SMDate } from "../helpers/datetime";
|
||||
import { imageLoad, imageMedium } from "../helpers/image";
|
||||
import {
|
||||
excerpt,
|
||||
replaceHtmlEntites,
|
||||
stringToNumber,
|
||||
stripHtmlTags,
|
||||
} from "../helpers/string";
|
||||
import { isUUID } from "../helpers/uuid";
|
||||
import SMButton from "./SMButton.vue";
|
||||
|
||||
const props = defineProps({
|
||||
@@ -160,8 +152,9 @@ const props = defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
let styleObject = reactive({});
|
||||
let imageUrl = ref("");
|
||||
let styleObject = {
|
||||
backgroundImage: `url('${props.image}')`,
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a human readable date based on props.date and props.endDate.
|
||||
@@ -229,32 +222,6 @@ const computedPrice = computed(() => {
|
||||
|
||||
return props.price;
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
if (props.image && props.image.length > 0 && isUUID(props.image)) {
|
||||
api.get({ url: "/media/{medium}", params: { medium: props.image } })
|
||||
.then((result) => {
|
||||
const data = result.data as MediaResponse;
|
||||
|
||||
if (data && data.medium) {
|
||||
imageLoad(data.medium.url, (url) => {
|
||||
imageUrl.value = url;
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
/* empty */
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => imageUrl.value,
|
||||
(value) => {
|
||||
const url = imageMedium(value);
|
||||
styleObject["backgroundImage"] = `url('${url}')`;
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -29,8 +29,9 @@
|
||||
@dblclick="handleDblClickItem(item.id)">
|
||||
<div
|
||||
:style="{
|
||||
backgroundImage: `url('${getFilePreview(
|
||||
item.url
|
||||
backgroundImage: `url('${mediaGetVariantUrl(
|
||||
item,
|
||||
'small'
|
||||
)}')`,
|
||||
}"
|
||||
class="media-image"></div>
|
||||
@@ -104,13 +105,14 @@ import { closeDialog } from "../SMDialog";
|
||||
import { api } from "../../helpers/api";
|
||||
import { Media, MediaCollection, MediaResponse } from "../../helpers/api.types";
|
||||
import { bytesReadable } from "../../helpers/types";
|
||||
import { getFilePreview } from "../../helpers/utils";
|
||||
import { useApplicationStore } from "../../store/ApplicationStore";
|
||||
import SMButton from "../SMButton.vue";
|
||||
import SMFormCard from "../SMFormCard.vue";
|
||||
import SMFormFooter from "../SMFormFooter.vue";
|
||||
import SMLoadingIcon from "../SMLoadingIcon.vue";
|
||||
import SMMessage from "../SMMessage.vue";
|
||||
import { mediaGetVariantUrl } from "../../helpers/media";
|
||||
import { toTitleCase } from "../../helpers/string";
|
||||
|
||||
const props = defineProps({
|
||||
mime: {
|
||||
@@ -390,6 +392,53 @@ const handleChangeUpload = async () => {
|
||||
if (result.data) {
|
||||
const data = result.data as MediaResponse;
|
||||
|
||||
if (
|
||||
data.medium.status != "" &&
|
||||
data.medium.status.startsWith("Failed") == false
|
||||
) {
|
||||
dialogLoadingMessage.value = `${data.medium.status}...`;
|
||||
|
||||
let mediaProcessed = false;
|
||||
|
||||
while (mediaProcessed == false) {
|
||||
await new Promise((resolve) =>
|
||||
setTimeout(resolve, 500)
|
||||
);
|
||||
|
||||
try {
|
||||
let updateResult = await api.get({
|
||||
url: "/media/{id}",
|
||||
params: {
|
||||
id: data.medium.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (updateResult.data) {
|
||||
const updateData =
|
||||
updateResult.data as MediaResponse;
|
||||
if (
|
||||
updateData.medium.status == "" &&
|
||||
data.medium.status.startsWith(
|
||||
"Failed"
|
||||
) == false
|
||||
) {
|
||||
mediaProcessed = true;
|
||||
} else {
|
||||
dialogLoadingMessage.value = `${updateData.medium.status}...`;
|
||||
}
|
||||
} else {
|
||||
throw "error";
|
||||
}
|
||||
} catch {
|
||||
mediaProcessed = true;
|
||||
formMessage.value =
|
||||
"An server error occurred processing the file";
|
||||
}
|
||||
}
|
||||
|
||||
dialogLoadingMessage.value;
|
||||
}
|
||||
|
||||
closeDialog(data.medium);
|
||||
} else {
|
||||
formMessage.value =
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
:key="item.event.id"
|
||||
:to="{ name: 'event-view', params: { id: item.event.id } }"
|
||||
:title="item.event.title"
|
||||
:image="item.event.hero"
|
||||
:image="mediaGetVariantUrl(item.event.hero, 'medium')"
|
||||
:show-time="true"
|
||||
:date="item.event.start_at"
|
||||
:end-date="item.event.end_at"
|
||||
@@ -67,6 +67,7 @@ import SMToolbar from "../components/SMToolbar.vue";
|
||||
import { api } from "../helpers/api";
|
||||
import { Event, EventCollection } from "../helpers/api.types";
|
||||
import { SMDate } from "../helpers/datetime";
|
||||
import { mediaGetVariantUrl } from "../helpers/media";
|
||||
|
||||
interface EventData {
|
||||
event: Event;
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
:page-error="pageError">
|
||||
<div
|
||||
class="sm-workshop-image"
|
||||
:style="{ backgroundImage: `url('${imageUrl}')` }"></div>
|
||||
:style="{
|
||||
backgroundImage: `url('${mediaGetVariantUrl(event.hero)}')`,
|
||||
}"></div>
|
||||
<SMContainer>
|
||||
<SMMessage
|
||||
v-if="formMessage"
|
||||
@@ -122,11 +124,11 @@ import SMHTML from "../components/SMHTML.vue";
|
||||
import SMMessage from "../components/SMMessage.vue";
|
||||
import SMAttachments from "../components/SMAttachments.vue";
|
||||
import { api } from "../helpers/api";
|
||||
import { Event, EventResponse, MediaResponse } from "../helpers/api.types";
|
||||
import { Event, EventResponse } from "../helpers/api.types";
|
||||
import { SMDate } from "../helpers/datetime";
|
||||
import { imageLoad, imageXXLarge } from "../helpers/image";
|
||||
import { stringToNumber } from "../helpers/string";
|
||||
import { useApplicationStore } from "../store/ApplicationStore";
|
||||
import { mediaGetVariantUrl } from "../helpers/media";
|
||||
|
||||
const applicationStore = useApplicationStore();
|
||||
|
||||
@@ -135,8 +137,6 @@ const applicationStore = useApplicationStore();
|
||||
*/
|
||||
const event: Ref<Event | null> = ref(null);
|
||||
|
||||
const imageUrl = ref("");
|
||||
|
||||
const route = useRoute();
|
||||
const pageLoading = ref(true);
|
||||
|
||||
@@ -283,7 +283,6 @@ const handleLoad = async () => {
|
||||
}).format("yyyy/MM/dd HH:mm:ss");
|
||||
|
||||
applicationStore.setDynamicTitle(event.value.title);
|
||||
handleLoadImage();
|
||||
} else {
|
||||
pageError.value = 404;
|
||||
}
|
||||
@@ -300,30 +299,6 @@ const handleLoad = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Load the hero image.
|
||||
*/
|
||||
const handleLoadImage = async () => {
|
||||
api.get({
|
||||
url: "/media/{medium}",
|
||||
params: {
|
||||
medium: event.value.hero,
|
||||
},
|
||||
})
|
||||
.then((result) => {
|
||||
const data = result.data as MediaResponse;
|
||||
|
||||
if (data && data.medium) {
|
||||
imageLoad(imageXXLarge(data.medium.url), (url) => {
|
||||
imageUrl.value = url;
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
/* empty */
|
||||
});
|
||||
};
|
||||
|
||||
handleLoad();
|
||||
</script>
|
||||
|
||||
|
||||
@@ -139,6 +139,7 @@ import { Form, FormControl } from "../helpers/form";
|
||||
import { excerpt } from "../helpers/string";
|
||||
import { And, Email, Required } from "../helpers/validate";
|
||||
import { useToastStore } from "../store/ToastStore";
|
||||
import { mediaGetVariantUrl } from "../helpers/media";
|
||||
|
||||
const slides = ref([]);
|
||||
const { executeRecaptcha, recaptchaLoaded } = useReCaptcha();
|
||||
@@ -163,8 +164,10 @@ const handleLoad = async () => {
|
||||
limit: 3,
|
||||
},
|
||||
})
|
||||
.catch(() => {
|
||||
hasError = true;
|
||||
.catch((e) => {
|
||||
if (e.status != 404) {
|
||||
hasError = true;
|
||||
}
|
||||
}),
|
||||
api
|
||||
.get({
|
||||
@@ -178,8 +181,10 @@ const handleLoad = async () => {
|
||||
}),
|
||||
},
|
||||
})
|
||||
.catch(() => {
|
||||
hasError = true;
|
||||
.catch((e) => {
|
||||
if (e.status != 404) {
|
||||
hasError = true;
|
||||
}
|
||||
}),
|
||||
]);
|
||||
|
||||
@@ -191,7 +196,7 @@ const handleLoad = async () => {
|
||||
posts.push({
|
||||
title: post.title,
|
||||
content: excerpt(post.content, 200),
|
||||
image: post.hero,
|
||||
image: mediaGetVariantUrl(post.hero),
|
||||
url: { name: "post-view", params: { slug: post.slug } },
|
||||
cta: "Read More...",
|
||||
});
|
||||
@@ -203,13 +208,14 @@ const handleLoad = async () => {
|
||||
events.push({
|
||||
title: event.title,
|
||||
content: excerpt(event.content, 200),
|
||||
image: event.hero,
|
||||
image: mediaGetVariantUrl(event.hero),
|
||||
url: { name: "event-view", params: { id: event.id } },
|
||||
cta: "View Workshop",
|
||||
});
|
||||
});
|
||||
}
|
||||
} catch {
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
hasError = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<SMPanel
|
||||
v-for="post in posts"
|
||||
:key="post.id"
|
||||
:image="post.hero"
|
||||
:image="mediaGetVariantUrl(post.hero, 'medium')"
|
||||
:to="{ name: 'post-view', params: { slug: post.slug } }"
|
||||
:title="post.title"
|
||||
:date="post.publish_at"
|
||||
@@ -39,6 +39,7 @@ import SMPanelList from "../components/SMPanelList.vue";
|
||||
import { api } from "../helpers/api";
|
||||
import { Post, PostCollection } from "../helpers/api.types";
|
||||
import { SMDate } from "../helpers/datetime";
|
||||
import { mediaGetVariantUrl } from "../helpers/media";
|
||||
|
||||
const message = ref("");
|
||||
const pageLoading = ref(true);
|
||||
|
||||
@@ -6,14 +6,16 @@
|
||||
:page-error="pageError">
|
||||
<div
|
||||
class="sm-heading-image"
|
||||
:style="{ backgroundImage: `url('${imageUrl}')` }"></div>
|
||||
:style="{
|
||||
backgroundImage: `url('${mediaGetVariantUrl(post.hero)}')`,
|
||||
}"></div>
|
||||
<SMContainer>
|
||||
<div class="sm-heading-info">
|
||||
<h1>{{ post.title }}</h1>
|
||||
<div class="sm-date-author small">
|
||||
<ion-icon name="calendar-outline" />
|
||||
{{ formattedPublishAt(post.publish_at) }}, by
|
||||
{{ postUser.username }}
|
||||
{{ post.user.username }}
|
||||
</div>
|
||||
</div>
|
||||
<SMHTML :html="post.content" />
|
||||
@@ -28,16 +30,10 @@ import { useRoute } from "vue-router";
|
||||
import SMAttachments from "../components/SMAttachments.vue";
|
||||
import SMHTML from "../components/SMHTML.vue";
|
||||
import { api } from "../helpers/api";
|
||||
import {
|
||||
MediaResponse,
|
||||
Post,
|
||||
PostCollection,
|
||||
User,
|
||||
UserResponse,
|
||||
} from "../helpers/api.types";
|
||||
import { Post, PostCollection, User } from "../helpers/api.types";
|
||||
import { SMDate } from "../helpers/datetime";
|
||||
import { imageLoad, imageXXLarge } from "../helpers/image";
|
||||
import { useApplicationStore } from "../store/ApplicationStore";
|
||||
import { mediaGetVariantUrl } from "../helpers/media";
|
||||
|
||||
const applicationStore = useApplicationStore();
|
||||
|
||||
@@ -56,40 +52,11 @@ let pageError = ref(200);
|
||||
*/
|
||||
let pageLoading = ref(false);
|
||||
|
||||
/**
|
||||
* Post styles.
|
||||
*/
|
||||
const imageUrl = ref("");
|
||||
|
||||
/**
|
||||
* Post user.
|
||||
*/
|
||||
let postUser: User | null = null;
|
||||
|
||||
/**
|
||||
* Load the hero image.
|
||||
*/
|
||||
const handleLoadImage = async () => {
|
||||
api.get({
|
||||
url: "/media/{medium}",
|
||||
params: {
|
||||
medium: post.value.hero,
|
||||
},
|
||||
})
|
||||
.then((result) => {
|
||||
const data = result.data as MediaResponse;
|
||||
|
||||
if (data && data.medium) {
|
||||
imageLoad(imageXXLarge(data.medium.url), (url) => {
|
||||
imageUrl.value = url;
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
/* empty */
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Load the page data.
|
||||
*/
|
||||
@@ -118,44 +85,6 @@ const handleLoad = async () => {
|
||||
}).format("yyyy/MM/dd HH:mm:ss");
|
||||
|
||||
applicationStore.setDynamicTitle(post.value.title);
|
||||
handleLoadImage();
|
||||
|
||||
// Get hero image
|
||||
try {
|
||||
let mediumResult = await api.get({
|
||||
url: "/media/{medium}",
|
||||
params: {
|
||||
medium: post.value.hero,
|
||||
},
|
||||
});
|
||||
|
||||
const mediumData = mediumResult.data as MediaResponse;
|
||||
|
||||
if (mediumData && mediumData.medium) {
|
||||
const url = imageXXLarge(mediumData.medium.url);
|
||||
styleObject["backgroundImage"] = `url('${url}')`;
|
||||
}
|
||||
} catch {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
// Get user data
|
||||
try {
|
||||
let userResult = await api.get({
|
||||
url: "/users/{id}",
|
||||
params: {
|
||||
id: post.value.user_id,
|
||||
},
|
||||
});
|
||||
|
||||
const userData = userResult.data as UserResponse;
|
||||
|
||||
if (userData && userData.user) {
|
||||
postUser = userData.user;
|
||||
}
|
||||
} catch {
|
||||
/* empty */
|
||||
}
|
||||
} else {
|
||||
pageError.value = 404;
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ const loadData = async () => {
|
||||
form.controls.content.value = data.event.content
|
||||
? data.event.content
|
||||
: "";
|
||||
form.controls.hero.value = data.event.hero;
|
||||
form.controls.hero.value = data.event.hero.id;
|
||||
form.controls.price.value = data.event.price;
|
||||
form.controls.ages.value = data.event.ages;
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ const loadData = async () => {
|
||||
if (data && data.post) {
|
||||
form.controls.title.value = data.post.title;
|
||||
form.controls.slug.value = data.post.slug;
|
||||
form.controls.user_id.value = data.post.user_id;
|
||||
form.controls.user_id.value = data.post.user.id;
|
||||
form.controls.content.value = data.post.content;
|
||||
form.controls.publish_at.value = data.post.publish_at
|
||||
? new SMDate(data.post.publish_at, {
|
||||
@@ -169,7 +169,7 @@ const loadData = async () => {
|
||||
}).format("dd/MM/yyyy HH:mm")
|
||||
: "";
|
||||
form.controls.content.value = data.post.content;
|
||||
form.controls.hero.value = data.post.hero;
|
||||
form.controls.hero.value = data.post.hero.id;
|
||||
|
||||
attachments.value = (data.post.attachments || []).map(function (
|
||||
attachment
|
||||
|
||||
Reference in New Issue
Block a user