377 lines
9.6 KiB
Vue
377 lines
9.6 KiB
Vue
<script setup>
|
|
import CloseIcon from '../assets/icons/close.svg'
|
|
import FolderIcon from '../assets/icons/folder.svg'
|
|
import FileIcon from '../assets/icons/file.svg'
|
|
import ReloadIcon from '../assets/icons/reload.svg'
|
|
</script>
|
|
|
|
<template>
|
|
<div class="windowContainer" id="linkPannel" ref="linkPannel" :style="{top:coordY+'px', left:coordX+'px'}" @mousedown.left="$emit('focus')">
|
|
<Moveable
|
|
className="moveable"
|
|
:target="$refs.linkPannel"
|
|
:draggable="true"
|
|
@drag="onDrag"
|
|
/>
|
|
<!--TITRE-->
|
|
<div class="windowTitle">
|
|
<div class="titleContent">
|
|
<p>./{{fileName}}</p>
|
|
<div class="multiBtnContainer">
|
|
<button type="button" class="titleBtn" id="rootBtn" v-show="isNotRoot" @mousedown.stop @touchstart="dataFirstLoad" @click="dataFirstLoad">
|
|
<ReloadIcon name="close" class="icon"/>
|
|
</button>
|
|
<button type="button" class="titleBtn" @mousedown.stop @touchstart="$emit('close')" @click="closeClicked">
|
|
<CloseIcon name="close" class="icon"/>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!--CONTENU-->
|
|
<p id="emptyFolderText" v-show="emptyFolder">Oops! There is nothing to display here...</p>
|
|
<div v-show="displayedItems" class="theMatrix" @mousedown.stop @touchstart.stop @reload="dataFirstLoad">
|
|
<div class="itemStyle" v-for="item in displayedItems" :class="{selectedStyle:item.isSelected, displayStyle: !item.isSelected}" :key="item.caption" @click="itemIsClicked(item)">
|
|
<component :is="item.type==='folder'? FolderIcon : FileIcon" class="icon"/>
|
|
<p class="itemCaption">{{item.caption}}</p>
|
|
</div>
|
|
</div>
|
|
<div v-show="displayedItems" class="itemDesc" @touchstart.stop>
|
|
<p>{{displayedDescription}}</p>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
/*=====================LinkPannel CSS*/
|
|
.multiBtnContainer{
|
|
align-self: center;
|
|
display: flex;
|
|
flex-direction: row;
|
|
justify-content: space-around;
|
|
height: 100%;
|
|
align-items: center;
|
|
width:auto;
|
|
}
|
|
|
|
#emptyFolderText{
|
|
align-self:center;
|
|
margin-top: 33px;
|
|
pointer-events: none;
|
|
color: var(--accent-color);
|
|
font-family: 'lineal';
|
|
font-weight: lighter;
|
|
font-size: 16.1px;
|
|
}
|
|
|
|
.theMatrix{
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
|
grid-auto-rows: 180px;
|
|
gap: 10px;
|
|
width: 97%;
|
|
height: 70%;
|
|
overflow-y: auto;
|
|
align-items: center;
|
|
margin-left: 5px;
|
|
}
|
|
|
|
.itemDesc{
|
|
width: 90%;
|
|
height: 21%;
|
|
border-radius: 16.1px;
|
|
border-color: var(--accent-color);
|
|
border-style: solid;
|
|
border-width: thin;
|
|
margin-top: 2%;
|
|
|
|
color: var(--light-color);
|
|
font-family: 'velvelyne';
|
|
font-weight: lighter;
|
|
font-size: 16.1px;
|
|
pointer-events: all;
|
|
cursor:inherit;
|
|
|
|
align-self: center;
|
|
padding-left: 2%;
|
|
padding-right: 3.33%;
|
|
overflow-y: scroll;
|
|
}
|
|
|
|
.itemStyle{
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
padding-top: 13.12px;
|
|
border-radius: 8px;
|
|
width:90%;
|
|
height: auto;
|
|
border-style: solid;
|
|
border-width: thin;
|
|
border-color: transparent;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.itemStyle:hover{
|
|
border-color: var(--accent-color);
|
|
}
|
|
/*===============Not selected Item*/
|
|
.displayStyle{
|
|
color: var(--light-color);
|
|
border-style: solid;
|
|
border-width: thin;
|
|
border-color: transparent;
|
|
}
|
|
|
|
.displayStyle .icon{
|
|
height:auto;
|
|
width:50%;
|
|
fill: currentColor;
|
|
}
|
|
|
|
/*===============Seleted Item*/
|
|
.selectedStyle{
|
|
color: var(--accent-color);
|
|
border-style: solid;
|
|
border-width: thin;
|
|
border-color: transparent;
|
|
}
|
|
|
|
.selectedStyle .icon{
|
|
height:auto;
|
|
width:50%;
|
|
fill: currentColor;
|
|
}
|
|
|
|
.itemCaption{
|
|
text-align: center;
|
|
font-weight: lighter;
|
|
font-size: 16.1px;
|
|
pointer-events: all;
|
|
cursor:inherit;
|
|
}
|
|
|
|
.displayStyle .itemCaption{
|
|
color: var(--light-color);
|
|
font-family: 'velvelyne';
|
|
}
|
|
|
|
.selectedStyle .itemCaption{
|
|
color: var(--accent-color);
|
|
font-family: 'lineal'
|
|
}
|
|
|
|
.itemCaption:hover{
|
|
color: var(--accent-color);
|
|
}
|
|
|
|
#linkPannel{
|
|
background-color: var(--dark-color);
|
|
cursor:grab;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
justify-content: flex-start;
|
|
}
|
|
|
|
/*=====================format pc*/
|
|
@media(min-width:800px){
|
|
#linkPannel{
|
|
width:666px;
|
|
height:666px;
|
|
margin-left: -333px;
|
|
}
|
|
.theMatrix{
|
|
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
|
grid-auto-rows: 180px;
|
|
}
|
|
}
|
|
|
|
/*=====================format tel*/
|
|
@media(max-width:800px){
|
|
#linkPannel{
|
|
position:fixed;
|
|
width:333px;
|
|
height:666px;
|
|
}
|
|
.theMatrix{
|
|
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
|
grid-auto-rows: 180px;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
import Moveable from 'vue3-moveable'
|
|
const linksData = [
|
|
{
|
|
type: "folder",
|
|
isSelected: false,
|
|
caption: "Folder001",
|
|
description: "Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.",
|
|
children: [{
|
|
type: "folder",
|
|
isSelected: false,
|
|
caption: "test-open",
|
|
description: "Nothing for now x333",
|
|
children: []
|
|
},
|
|
{
|
|
type: "file",
|
|
isSelected: false,
|
|
caption: "READ-ME002.txt",
|
|
description: "Nothing for now x333",
|
|
src: ""
|
|
}]
|
|
},
|
|
{
|
|
type: "folder",
|
|
isSelected: false,
|
|
caption: "Folder002",
|
|
description: "Nothing for now x333",
|
|
children: []
|
|
},
|
|
{
|
|
type: "folder",
|
|
isSelected: false,
|
|
caption: "Folder333",
|
|
description: "Nothing for now x333",
|
|
children: []
|
|
},
|
|
{
|
|
type: "folder",
|
|
isSelected: false,
|
|
caption: "test",
|
|
description: "Nothing for now x333",
|
|
children: []
|
|
},
|
|
{
|
|
type: "file",
|
|
isSelected: false,
|
|
caption: "READ-ME.txt",
|
|
description: "Nothing for now x333",
|
|
src: ""
|
|
}
|
|
]
|
|
|
|
export default {
|
|
name : 'LinkPannel',
|
|
components:{
|
|
Moveable,
|
|
FileIcon,
|
|
FolderIcon
|
|
},
|
|
emits: ["focus","close"],
|
|
methods:{
|
|
onDrag({ target, transform }) {
|
|
target.style.transform = transform;
|
|
},
|
|
observeContainer(){
|
|
const container = document.getElementById("contentContainer");
|
|
|
|
if(!container){
|
|
console.error("container not found");
|
|
return
|
|
}
|
|
|
|
const observer = new ResizeObserver(entries=>{
|
|
const rect = entries[0].contentRect;
|
|
|
|
this.bodyWidth = rect.width;
|
|
this.bodyHeight = rect.height;
|
|
|
|
this.coordX = Math.random()*(this.bodyWidth-333);
|
|
this.coordY = Math.random()*(this.bodyHeight-333);
|
|
});
|
|
|
|
observer.observe(container);
|
|
},
|
|
dataFirstLoad(){
|
|
this.displayedItems = [...linksData];
|
|
console.log(this.displayedItems);
|
|
this.isNotRoot = false;
|
|
this.checkEmptyFolder();
|
|
this.displayedItems.forEach(it => {
|
|
it.isSelected = false;
|
|
});
|
|
this.displayedDescription = "Click an item to get more info !";
|
|
this.fileName = "ExternalLinks.333";
|
|
},
|
|
openFile(e){
|
|
this.$emit('focus');
|
|
if(e.type === 'folder'){
|
|
this.displayedItems = [...e.children];
|
|
this.checkEmptyFolder();
|
|
this.isNotRoot = true;
|
|
this.displayedDescription = e.description
|
|
if (this.bodyWidth>this.bodyHeight){
|
|
console.log('container dimensions:', this.bodyWidth, this.bodyHeight);
|
|
this.fileName =".../"+ e.caption;
|
|
}else{
|
|
this.fileName += "/" + e.caption;
|
|
}
|
|
} else {
|
|
|
|
}
|
|
},
|
|
selectFile(e){
|
|
this.$emit('focus');
|
|
this.displayedItems.forEach(it => {
|
|
it.isSelected = false;
|
|
})
|
|
e.isSelected = true;
|
|
this.displayedDescription = e.description;
|
|
},
|
|
itemIsClicked(e){
|
|
if (!this.dblClickTimer || this.lastClickedItem !== e){
|
|
clearTimeout(this.dblClickTimer);
|
|
this.lastClickedItem = e;
|
|
this.dblClickTimer = setTimeout(() => {
|
|
this.selectFile(e);
|
|
this.dblClickTimer = null;
|
|
this.lastClickedItem = null;
|
|
}, 200);
|
|
}else{
|
|
clearTimeout(this.dblClickTimer);
|
|
this.dblClickTimer = null;
|
|
this.lastClickedItem = null;
|
|
this.openFile(e);
|
|
}
|
|
},
|
|
checkEmptyFolder(){
|
|
if (this.displayedItems.length === 0){
|
|
this.emptyFolder = true;
|
|
this.displayedItems = null;
|
|
}else{
|
|
this.emptyFolder = false;
|
|
}
|
|
},
|
|
closeClicked(){
|
|
this.dataFirstLoad();
|
|
this.$emit('close');
|
|
}
|
|
},
|
|
data(){
|
|
return {
|
|
lastClickedItem: null,
|
|
dblClickTimer: null,
|
|
bodyHeight:0,
|
|
bodyWidth:0,
|
|
coordX:0,
|
|
coordY:0,
|
|
displayedItems: null,
|
|
emptyFolder: false,
|
|
displayedDescription: "",
|
|
fileName: "",
|
|
isNotRoot : false
|
|
}
|
|
},
|
|
mounted(){
|
|
this.$nextTick(() => {
|
|
this.observeContainer()
|
|
});
|
|
this.dataFirstLoad();
|
|
console.log("Contact pannel is loaded!");
|
|
}
|
|
};
|
|
</script>
|