details view image component refactor
All checks were successful
/ Make image (push) Successful in 39s
All checks were successful
/ Make image (push) Successful in 39s
This commit is contained in:
parent
9d80345b77
commit
bb40d17e6b
5 changed files with 118 additions and 39 deletions
|
|
@ -20,12 +20,27 @@
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.center-button-container {
|
.button-container-center {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.button-container-evenly {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between !important;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-container-evenly .n-button {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-gap {
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.center-button {
|
.center-button {
|
||||||
min-width: 320px;
|
min-width: 320px;
|
||||||
}
|
}
|
||||||
|
|
@ -137,3 +152,17 @@ body,
|
||||||
.main-content {
|
.main-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.image-preview-modal {
|
||||||
|
width: 80%;
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
.image-preview-modal .n-card__content {
|
||||||
|
padding: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.preview-modal-image {
|
||||||
|
max-width: 99%;
|
||||||
|
max-height: 70vh;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ onMounted(() => {
|
||||||
</n-card>
|
</n-card>
|
||||||
<div v-else>Not found</div>
|
<div v-else>Not found</div>
|
||||||
|
|
||||||
<div class="center-button-container">
|
<div class="button-container-center">
|
||||||
<n-button type="error" class="center-button" @click="onDelete">Delete</n-button>
|
<n-button type="error" class="center-button" @click="onDelete">Delete</n-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,27 @@ function onModalClose() {
|
||||||
previewImageUrl.value = ''
|
previewImageUrl.value = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
function beforeUpload({ fileList: newFileList }) {
|
const fileInput = ref(null)
|
||||||
return newFileList.length <= 1
|
|
||||||
|
function triggerFileInput() {
|
||||||
|
fileInput.value?.click()
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFileInputChange(event) {
|
||||||
|
const files = event.target.files
|
||||||
|
if (!files || files.length === 0) return
|
||||||
|
|
||||||
|
const file = files[0]
|
||||||
|
handleUpload({
|
||||||
|
fileList: [
|
||||||
|
{
|
||||||
|
file,
|
||||||
|
name: file.name,
|
||||||
|
status: 'pending',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
event.target.value = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleUpload({ fileList: newFileList }) {
|
async function handleUpload({ fileList: newFileList }) {
|
||||||
|
|
@ -100,36 +119,30 @@ const cancelDelete = () => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<n-upload
|
<div v-if="fileList.length === 0" class="upload-wrapper" @click="triggerFileInput">
|
||||||
v-model:file-list="fileList"
|
|
||||||
:default-upload="false"
|
|
||||||
list-type="image-card"
|
|
||||||
:max="1"
|
|
||||||
:before-upload="beforeUpload"
|
|
||||||
@before-preview="handlePreview"
|
|
||||||
@change="handleUpload"
|
|
||||||
@remove="deleteImageHandler"
|
|
||||||
>
|
|
||||||
<div class="upload-trigger" v-if="fileList.length === 0">
|
|
||||||
<BoxIcon class="upload-icon" />
|
<BoxIcon class="upload-icon" />
|
||||||
<span class="upload-text">Click to Upload</span>
|
<span class="upload-text">Click to Upload</span>
|
||||||
</div>
|
</div>
|
||||||
</n-upload>
|
|
||||||
|
|
||||||
<n-modal
|
<div v-else class="preview-container clickable-image">
|
||||||
v-model:show="showModal"
|
<div>
|
||||||
preset="card"
|
|
||||||
style="width: 600px"
|
|
||||||
title="Preview"
|
|
||||||
@after-leave="onModalClose"
|
|
||||||
>
|
|
||||||
<img
|
<img
|
||||||
:src="previewImageUrl"
|
:src="fileList[0].url"
|
||||||
style="width: 100%; max-height: 600px; object-fit: contain"
|
|
||||||
alt="Preview"
|
alt="Preview"
|
||||||
|
class="preview-image"
|
||||||
|
@click="triggerFileInput"
|
||||||
/>
|
/>
|
||||||
</n-modal>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="button-container-evenly button-gap">
|
||||||
|
<n-button type="primary" @click="handlePreview(fileList[0])">Preview</n-button>
|
||||||
|
<n-button type="error" @click="deleteImageHandler">Delete</n-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<n-modal v-model:show="showModal" preset="card" title="Preview" @after-leave="onModalClose" class="image-preview-modal">
|
||||||
|
<img :src="previewImageUrl" alt="Preview" class="preview-modal-image"/>
|
||||||
|
</n-modal>
|
||||||
|
|
||||||
<n-modal v-model:show="showConfirmDelete" preset="dialog" title="Confirmation">
|
<n-modal v-model:show="showConfirmDelete" preset="dialog" title="Confirmation">
|
||||||
<template #default>
|
<template #default>
|
||||||
|
|
@ -140,13 +153,22 @@ const cancelDelete = () => {
|
||||||
<n-button @click="cancelDelete">Cancel</n-button>
|
<n-button @click="cancelDelete">Cancel</n-button>
|
||||||
</template>
|
</template>
|
||||||
</n-modal>
|
</n-modal>
|
||||||
|
|
||||||
|
<input
|
||||||
|
ref="fileInput"
|
||||||
|
type="file"
|
||||||
|
accept="image/*"
|
||||||
|
style="display: none"
|
||||||
|
@change="onFileInputChange"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.upload-trigger {
|
.upload-wrapper {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
max-height: 600px;
|
max-width: 300px;
|
||||||
min-height: 180px;
|
height: 300px;
|
||||||
|
max-height: 300px;
|
||||||
border: 1px dashed #ccc;
|
border: 1px dashed #ccc;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background-color: #fafafa;
|
background-color: #fafafa;
|
||||||
|
|
@ -160,14 +182,16 @@ const cancelDelete = () => {
|
||||||
border-color 0.2s ease;
|
border-color 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-trigger:hover {
|
.upload-wrapper:hover {
|
||||||
border-color: #18a058;
|
border-color: #18a058;
|
||||||
background-color: #f0fdf4;
|
background-color: #f0fdf4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-icon {
|
.upload-icon {
|
||||||
width: 150px;
|
width: 150px;
|
||||||
|
max-width: 150px;
|
||||||
height: 150px;
|
height: 150px;
|
||||||
|
max-height: 150px;
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -175,6 +199,32 @@ const cancelDelete = () => {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #555;
|
color: #555;
|
||||||
|
background-color: rgba(24, 160, 88, 0.4);
|
||||||
|
padding: 6px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.preview-container {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 400px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-image {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
display: block;
|
||||||
|
max-width: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clickable-image {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
}
|
||||||
|
.clickable-image:hover {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ const insertAutoCompletedLink = () => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="props.origin === 'mandarake'" class="center-button-container mb-10">
|
<div v-if="props.origin === 'mandarake'" class="button-container-center mb-10">
|
||||||
<n-button type="warning" class="center-button" @click="insertAutoCompletedLink"
|
<n-button type="warning" class="center-button" @click="insertAutoCompletedLink"
|
||||||
>Insert auto-completed link</n-button
|
>Insert auto-completed link</n-button
|
||||||
>
|
>
|
||||||
|
|
@ -127,7 +127,7 @@ const insertAutoCompletedLink = () => {
|
||||||
<n-button size="small" type="primary" :loading="loading" @click="save">Save</n-button>
|
<n-button size="small" type="primary" :loading="loading" @click="save">Save</n-button>
|
||||||
<n-button size="small" @click="cancel">Cancel</n-button>
|
<n-button size="small" @click="cancel">Cancel</n-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="center-button-container">
|
<div class="button-container-center">
|
||||||
<n-button type="error" class="center-button" @click="clearLink">Clear link</n-button>
|
<n-button type="error" class="center-button" @click="clearLink">Clear link</n-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ const onLogout = () => {
|
||||||
{{ formattedDate }}
|
{{ formattedDate }}
|
||||||
</n-thing>
|
</n-thing>
|
||||||
</n-list-item>
|
</n-list-item>
|
||||||
<div class="center-button-container">
|
<div class="button-container-center">
|
||||||
<n-button type="info" class="center-button" @click="onLogout">Log out</n-button>
|
<n-button type="info" class="center-button" @click="onLogout">Log out</n-button>
|
||||||
</div>
|
</div>
|
||||||
</n-list>
|
</n-list>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue